Android Spinner - Как отключить выбор списка по умолчанию

У меня есть форма Android, которая должна обновляться в зависимости от выбора. Форма в настоящее время состоит из 2 прядильщиков (A и B). Спиннер B не создается, пока не будет сделан выбор Spinner A. После того, как выбор сделан, B будет отображаться в представлении, и его содержимое динамически заполняется на основе выбора A. Вот мой код:

public class MyForm extends Activity 
{   
    private final int SEL_ACTIVATE = 0;
    private final int SEL_DEACTIVATE = 1;

    private static final String[] actionList = {"Activate", "Deactivate" };

    @Override
    public void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        table = (TableLayout) findViewById(R.id.table);

        showListA(table);
    }

    public void showListA(View v)
    {        
        rowAction = new TableRow(this);

        Spinner spinner = new Spinner(this);
        spinner.setPrompt("Select...");
        spinner.setOnItemSelectedListener(
            new OnItemSelectedListener() 
            {
                public void onItemSelected(AdapterView<?> parent, View v, int position, long id) 
                {
                    switch (position)
                    {
                    case SEL_ACTIVATE:
                    case SEL_DEACTIVATE:
                        showListB(v);
                        break;
                    }
                }

                public void onNothingSelected(AdapterView<?> arg0) 
                {
                    // TODO Auto-generated method stub
                }
        });

        ArrayAdapter<String> adapter = new ArrayAdapter<String> (this, android.R.layout.simple_spinner_item, actionList);
        adapter.setDropDownViewResource(android.R.layout.simple_dropdown_item_1line);
        spinner.setAdapter(adapter);

        rowAction.addView(tvAction);
        rowAction.addView(spinner);

        table.addView(rowAction, new TableLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
    }

    ...
}

Этот код работает правильно. Когда в списке выбраны «Активировать» или «Деактивировать», выполняется showListB(), что очень похоже на showListA() в том, как он создает новую строку, содержащую метку и счетчик.

Проблема в том, что по умолчанию «Активировать» отображается в Spinner, который выполняет showListB(), и сразу же создается вторая часть формы на основе параметра «Активировать». Единственный обходной путь, который я могу придумать, - это добавить третье поле в Spinner следующим образом:

private static final String[] actionList = {"None", "Activate", "Deactivate" };

...

switch (position)
{
case SEL_NONE:
    break;
case SEL_ACTIVATE:
case SEL_DEACTIVATE:
    showListB(v);
    break;
}

Это работает ... но мне не нужен третий вариант в списке. Я просто хочу, чтобы он по умолчанию был пустым или отображал какой-то текст «подсказки», которого нет в списке после его нажатия. Это возможно?

Спасибо

РЕДАКТИРОВАТЬ:

xml содержимое:

<Spinner
    android:id="@+id/spinnerAction"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>  

person linsek    schedule 13.12.2010    source источник


Ответы (5)


Мои data-sizes.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array name="chunks">
        <item>2</item>
        <item>4</item>
        <item>8</item>
        <item>16</item>
        <item>32</item>
    </string-array>
</resources>

В main.xml:

<Spinner android:id="@+id/spinnerSize"  
android:layout_marginLeft="50px"
android:layout_width="fill_parent"                  
android:drawSelectorOnTop="true"
android:layout_marginTop="5dip"
android:prompt="@string/SelectSize"
android:layout_marginRight="30px"
android:layout_height="35px" /> 

В коде Java:

Spinner spinnerSize;
ArrayAdapter adapter;

...

spinnerSize = (Spinner)findViewById(R.id.spinnerSize);
adapter = ArrayAdapter.createFromResource(this, R.array.chunks, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinnerSize.setAdapter(adapter);
spinnerSize.setOnItemSelectedListener(new MyOnItemSelectedListener());

...

class MyOnItemSelectedListener implements OnItemSelectedListener {

    public void onItemSelected(AdapterView<?> parent,
        View view, int pos, long id) {
        chunkSize = new Integer(parent.getItemAtPosition(pos).toString()).intValue();
    }
    public void onNothingSelected(AdapterView<?> parent) {
      // Dummy
    }
}

Итак, хотя я вижу 2 как свой первый элемент по умолчанию, ничего не происходит, пока пользователь не выберет его.

Надеюсь это поможет!

person TheCottonSilk    schedule 23.01.2011
comment
Пожалуйста, укажите причины, по которым вы считаете, что ответ бесполезен (-1), чтобы все могли понять, почему этот ответ нехороший, и показать лучший способ сделать это! Спасибо. - person TheCottonSilk; 03.11.2011
comment
Чтобы уточнить, это работает, потому что вы устанавливаете OnItemSelectedListener после, когда вы устанавливаете Adapter правильно? - person Tony Chan; 09.10.2013
comment
Что такое переменная chunkSize? - person CACuzcatlan; 22.03.2017

Если хотите, есть декоратор spinnerAdapter, который автоматически добавляет значение по умолчанию:



    protected class SpinnerAdapterWithNoValue implements SpinnerAdapter {

        private SpinnerAdapter _current;
        private final static String defaultValue = "Choisir";

        public SpinnerAdapterWithNoValue(SpinnerAdapter base) {
            _current = base;
        }

        @Override
        public int getCount() {
            return _current.getCount() + 1;
        }

        @Override
        public Object getItem(int position) {
            if (position == 0 || position == -1) {
                return null;
            }
            return _current.getItem(position - 1);
        }

        @Override
        public long getItemId(int position) {
            if (position == 0 || position == -1) {
                return -1;
            }
            return _current.getItemId(position - 1);
        }

        @Override
        public int getItemViewType(int position) {
            if (position == 0 || position == -1) {
                return -1;
            }
            return _current.getItemViewType(position - 1);
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            if (position == 0 || position == -1) {
                final TextView v = (TextView) ((LayoutInflater) getContext().getSystemService(
                        Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.spinner_text, parent, false);
                v.setText(defaultValue);
                return v;
            }
            return _current.getView(position - 1, convertView, parent);
        }

        @Override
        public int getViewTypeCount() {
            return _current.getViewTypeCount();
        }

        @Override
        public boolean hasStableIds() {
            return _current.hasStableIds();
        }

        @Override
        public boolean isEmpty() {
            return _current.isEmpty();
        }

        @Override
        public void registerDataSetObserver(DataSetObserver observer) {
            _current.registerDataSetObserver(observer);
        }

        @Override
        public void unregisterDataSetObserver(DataSetObserver observer) {
            // TODO Auto-generated method stub
            _current.unregisterDataSetObserver(observer);
        }

        @Override
        public View getDropDownView(int position, View convertView, ViewGroup parent) {
            // TODO Auto-generated method stub
            if (position == 0 || position == -1) {
                CheckedTextView v = (CheckedTextView) ((LayoutInflater) getContext().getSystemService(
                        Context.LAYOUT_INFLATER_SERVICE)).inflate(android.R.layout.simple_spinner_dropdown_item, parent,
                        false);
                v.setText(defaultValue);
                return v;
            }
            return _current.getDropDownView(position - 1, convertView, parent);
        }
    }


Затем вы можете создать свой собственный счетчик с помощью этого декоратора:



    public class SpinnerWithNoValue extends Spinner {

        public SpinnerWithNoValue(Context context) {
            super(context);
        }

        public SpinnerWithNoValue(Context context, AttributeSet attrs) {
            super(context, attrs);
        }

        public SpinnerWithNoValue(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
        }

        @Override
        public void setAdapter(SpinnerAdapter orig) {
            final SpinnerAdapter adapter = new SpinnerAdapterWithNoValue(orig);
            super.setAdapter(adapter);

            try {
                final Method m = AdapterView.class.getDeclaredMethod("setNextSelectedPositionInt", int.class);
                m.setAccessible(true);
                m.invoke(this, -1);

                final Method n = AdapterView.class.getDeclaredMethod("setSelectedPositionInt", int.class);
                n.setAccessible(true);
                n.invoke(this, -1);

            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }

        /*
         * getSelectedItem renvoi null si la valeur par defaut est séléctionnée
         * 
         * @see android.widget.AdapterView#getSelectedItem()
         */
        @Override
        public Object getSelectedItem() {
            return super.getSelectedItem();
        }
    }


Вам просто нужно изменить объявление счетчика в макете xml:



com.myproject.SpinnerWithNoValue


Если вы хотите, вы можете изменить код, чтобы установить текст по умолчанию в теге вашего счетчика.

person Henache Rémi    schedule 31.01.2013

У Spinner всегда будет выбор. Что вы можете сделать, так это сделать так, чтобы Spinner отображал что-то вроде «Выбрать» или «Выбрать вариант» ...

Для этого вы можете сделать свой список опций

actionList = {"Select", "Desactivate" }

и

public void onItemSelected(AdapterView<?> arg0, View arg1, int position, long id) {               
        actionList[0] = "Activate";
        ...
 }

или вы можете сделать что-то более сложное, например, переопределить представление счетчика или вместо этого поместить кнопку, на которой ничего нет, и при ее нажатии вы создаете свой счетчик.

person Marylia Gutierrez    schedule 07.11.2011

Попробуйте установить это в xml с атрибутом prompt:

android:prompt="@string/prompt"

Это также заполнит верхнюю часть диалогового окна счетчика.

Я упустил это из виду в документации. Подсказку нельзя применить напрямую. На атрибут подсказки необходимо ссылаться из другого источника. Попробуйте сослаться на строковое значение.

Документация с Android:

android:prompt

Since: API Level
 The prompt to display when the spinner's dialog is shown.
 Must be a reference to another resource, in the form "@[+][package:]type:name" or to a       theme attribute in the form "?[package:][type:]name".
This corresponds to the global attribute resource symbol prompt.
person Phobos    schedule 13.12.2010
comment
Я считаю, что делаю это в исходном коде Java через spinner.setPrompt("Available Actions");. Но я просто попытался добавить вашу исходную строку в XML и получил следующую ошибку: error: Error: String types not allowed (at 'prompt' with value 'test'). Что странно, потому что API для <Spinner> говорит, что приглашение должно быть допустимым аргументом ... - person linsek; 13.12.2010
comment
Я пропустил ссылку в документации. Необходимо указать подсказку. - person Phobos; 13.12.2010
comment
Извините, я не совсем слежу за вашим редактированием. Попробуйте сослаться на строковое значение? - person linsek; 14.12.2010
comment
это не работает. Приглашение просто дает счетчику название, оно не заменяет ни один из элементов. @Phobos прав, вы не можете сказать android:prompt="some text", что это должно быть android:prompt="@string/text_string" или что-то в этом роде - person dylan murphy; 17.06.2011

Я только начинаю разрабатывать приложения для Android и столкнулся с аналогичной проблемой; смог разобраться с этим, используя простое решение - это сработало для меня, надеюсь, что и для вас:

открытый класс AdmissionActivity расширяет активность, реализует OnItemSelectedListener {

int i;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    i=0;
            .........

           }

........ .....

public void onItemSelected(AdapterView<?> parent, View view, 
        int pos, long id){

    if(i!=0){
        //do wat you want;
    }
    else i=1;
            }
            //initially the activity will be loaded and nothing  will happen (since
              // i=0); and then appropriate action will be taken since i would hav been

// изменено на sumtng else

person MMss    schedule 09.02.2013