Как установить значение Spinner по умолчанию в null?

Я пытаюсь загрузить счетчик без выбранного значения. Как только пользователь выбирает значение, он переносит его на другую страницу.

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

мой класс spinner настроен так же, как Google:http://developer.android.com/resources/tutorials/views/hello-spinner.html

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

9 ответов


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

только если нет данных. Если у вас есть 1+ элементов SpinnerAdapter, the Spinner всегда есть выбор.

Spinners не предназначены для командной виджеты. Пользователи не будут ожидать выбора в Spinner чтобы начать работу. Пожалуйста, подумайте об использовании чего-то еще, например ListView или GridView, вместо a Spinner.


редактировать

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


кроме того, вы можете переопределить адаптер spinner и предоставить пустое представление для позиции 0 в методе getView и представление с высотой 0dp в getDropDownView метод.

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


это полная реализация идея поля Бурдо, а именно возврат специального начального представления (или пустого представления) в getView() для установки 0.

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

адаптер будет что-то вроде этих строк:

public class MySpinnerAdapter extends ArrayAdapter<MyModel> {

    public MySpinnerAdapter(Context context, List<MyModel> items) {
        super(context, R.layout.my_spinner_row, items);
    }

    @Override
    public View getDropDownView(int position, View convertView, @NonNull ViewGroup parent) {
        if (position == 0) {
            return initialSelection(true);
        }
        return getCustomView(position, convertView, parent);
    }

    @NonNull
    @Override
    public View getView(int position, View convertView, @NonNull ViewGroup parent) {
        if (position == 0) {
            return initialSelection(false);
        }
        return getCustomView(position, convertView, parent);
    }


    @Override
    public int getCount() {
        return super.getCount() + 1; // Adjust for initial selection item
    }

    private View initialSelection(boolean dropdown) {
        // Just an example using a simple TextView. Create whatever default view 
        // to suit your needs, inflating a separate layout if it's cleaner.
        TextView view = new TextView(getContext());
        view.setText(R.string.select_one);
        int spacing = getContext().getResources().getDimensionPixelSize(R.dimen.spacing_smaller);
        view.setPadding(0, spacing, 0, spacing);

        if (dropdown) { // Hidden when the dropdown is opened
            view.setHeight(0);
        }

        return view;
    }

    private View getCustomView(int position, View convertView, ViewGroup parent) {
        // Distinguish "real" spinner items (that can be reused) from initial selection item
        View row = convertView != null && !(convertView instanceof TextView) 
        ? convertView :
        LayoutInflater.from(getContext()).inflate(R.layout.my_spinner_row, parent, false);

        position = position - 1; // Adjust for initial selection item
        MyModel item = getItem(position);

        // ... Resolve views & populate with data ...

        return row;
    }

}

вот и все. Обратите внимание, что если вы используете OnItemSelectedListener С блесны, в onItemSelected() вам также придется настроить position чтобы учесть элемент по умолчанию, например:

if (position == 0) {
    return;
} else {
    position = position - 1;
}
MyModel selected = items.get(position);

в моем случае, хотя размер " 2 " отображается в спиннере, ничего не происходит, пока не будет сделан некоторый выбор!

у меня есть xml-файл (data_sizes.xml), в котором перечислены все значения spinner.

<?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

<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;

в публичной функции void-initControls (): Definition

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());

моя пряха слушатель:

/ * Spinner Listener */

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
    }
}

использование пользовательского макета spinner, как это:

<?xml version="1.0" encoding="utf-8"?>
<Spinner xmlns:android="http://schemas.android.com/apk/res/android"
          android:id="@+id/spinnerTarget"
          android:layout_width="fill_parent"
          android:layout_height="wrap_content"
          android:textSize="14dp"         
          android:textColor="#000000"/>

в работе:

    // populate the list
    ArrayList<String> dataList = new ArrayList<String>();
    for (int i = 0; i < 4; i++) {
        dataList.add("Item");
    }

    // set custom layout spinner_layout.xml and adapter
    Spinner spinnerObject = (Spinner) findViewById(R.id.spinnerObject);
    ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>(this, R.drawable.spinner_layout, dataList);
    dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    spinnerObject.setAdapter(dataAdapter);
    spinnerObject.setOnTouchListener(new View.OnTouchListener() { 

        public boolean onTouch(View v, MotionEvent event) {
            // to set value of first selection, because setOnItemSelectedListener will not dispatch if the user selects first element
            TextView spinnerTarget = (TextView)v.findViewById(R.id.spinnerTarget);
            spinnerTarget.setText(spinnerObject.getSelectedItem().toString());

            return false;
        }

    });
    spinnerObject.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
                private boolean selectionControl = true;

                public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
                    // just the first time
                    if(selectionControl){

                        // find TextView in layout 
                        TextView spinnerTarget = (TextView)parent.findViewById(R.id.spinnerTarget);
                        // set spinner text empty
                        spinnerTarget.setText("");
                        selectionControl = false;
                    }
                    else{
                        // select object
                    }
                }

                public void onNothingSelected(AdapterView<?> parent) {

                }
            });

слияние это:

private long previousItemId = 0;

@Override
public long getItemId(int position) {
    long nextItemId = random.nextInt(Integer.MAX_VALUE);
    while(previousItemId == nextItemId) {
        nextItemId = random.nextInt(Integer.MAX_VALUE);
    }
    previousItemId = nextItemId;
    return nextItemId;
}

С ответ:

public class SpinnerInteractionListener
        implements AdapterView.OnItemSelectedListener, View.OnTouchListener {

    private AdapterView.OnItemSelectedListener onItemSelectedListener;

    public SpinnerInteractionListener(AdapterView.OnItemSelectedListener selectedListener) {
        this.onItemSelectedListener = selectedListener;
    }

    boolean userSelect = false;

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        userSelect = true;
        return false;
    }

    @Override
    public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
        if(userSelect) {
            onItemSelectedListener.onItemSelected(parent, view, pos, id);
            userSelect = false;
        }
    }

    @Override
    public void onNothingSelected(AdapterView<?> parent) {
        if(userSelect) {
            onItemSelectedListener.onNothingSelected(parent);
            userSelect = false;
        }
    }
}

вы можете поместить первую ячейку в массив, чтобы она была пустой ({"","some","some",...}) и ничего не делать, если позиция 0;

public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
    if(position>0) {
        label.setText(MainActivity.questions[position - 1]);
    }
}
  • если вы заполните массив xml-файлом, вы можете позволить первому элементу пустым

мое решение, если у вас есть TextView как каждая строка spinner:

    // TODO: add a fake item as the last one of "items"
    final ArrayAdapter<String> adapter=new ArrayAdapter<String>(..,..,items) 
      {
      @Override
      public View getDropDownView(final int position,final View convertView,final ViewGroup parent)
        {
        final View dropDownView=super.getDropDownView(position,convertView,parent);
        ((TextView)dropDownView.findViewById(android.R.id.text1)).setHeight(position==getCount()-1?0:getDimensionFromAttribute(..,R.attr.dropdownListPreferredItemHeight));
        dropDownView.getLayoutParams().height=position==getCount()-1?0:LayoutParams.MATCH_PARENT;
        return dropDownView;
        }
      }

    ...
    spinner.setAdapter(adapter);
    _actionModeSpinnerView.setSelection(dataAdapter.getCount()-1,false);



  public static int getDimensionFromAttribute(final Context context,final int attr)
    {
    final TypedValue typedValue=new TypedValue();
    if(context.getTheme().resolveAttribute(attr,typedValue,true))
      return TypedValue.complexToDimensionPixelSize(typedValue.data,context.getResources().getDisplayMetrics());
    return 0;
    }

база на @Jonik answer я создал полнофункциональное расширение для ArrayAdapter

class SpinnerArrayAdapter<T> : ArrayAdapter<T> {

    private val selectText : String
    private val resource: Int
    private val fieldId : Int
    private val inflater : LayoutInflater

    constructor(context: Context?, resource: Int, objects: Array<T>, selectText : String? = null) : super(context, resource, objects) {
        this.selectText = selectText ?: context?.getString(R.string.spinner_default_select_text) ?: ""
        this.resource = resource
        this.fieldId = 0
        this.inflater = LayoutInflater.from(context)
    }
    constructor(context: Context?, resource : Int, objects: List<T>, selectText : String? = null) : super(context, resource, objects) {
        this.selectText = selectText ?: context?.getString(R.string.spinner_default_select_text) ?: ""
        this.resource = resource
        this.fieldId = 0
        this.inflater = LayoutInflater.from(context)
    }
    constructor(context: Context?, resource: Int, textViewResourceId: Int, objects: Array<T>, selectText : String? = null) : super(context, resource, textViewResourceId, objects) {
        this.selectText = selectText ?: context?.getString(R.string.spinner_default_select_text) ?: ""
        this.resource = resource
        this.fieldId = textViewResourceId
        this.inflater = LayoutInflater.from(context)
    }
    constructor(context: Context?, resource : Int, textViewResourceId: Int, objects: List<T>, selectText : String? = null) : super(context, resource, textViewResourceId,  objects) {
        this.selectText = selectText ?: context?.getString(R.string.spinner_default_select_text) ?: ""
        this.resource = resource
        this.fieldId = textViewResourceId
        this.inflater = LayoutInflater.from(context)
    }

    override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup?): View {
        if(position == 0) {
            return initialSelection(true)
        }

        return createViewFromResource(inflater, position -1, convertView, parent, resource)
    }

    override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
        if(position == 0) {
            return initialSelection(false)
        }
        return createViewFromResource(inflater, position -1, convertView, parent, resource)
    }

    override fun getCount(): Int {
        return super.getCount() + 1 // adjust for initial selection
    }

    private fun initialSelection(inDropDown: Boolean) : View {
        // Just simple TextView as initial selection.
        val view = TextView(context)
        view.setText(selectText)
        view.setPadding(8, 0, 8, 0)

        if(inDropDown) {
            // Hide when dropdown is open
            view.height = 0
        }
        return view
    }

    private fun createViewFromResource(inflater: LayoutInflater, position: Int,
                                       @Nullable convertView: View?, parent: ViewGroup?, resource: Int): View {
        val view: View
        val text: TextView?

        if (convertView == null || (convertView is TextView)) {
            view = inflater.inflate(resource, parent, false)
        } else {
            view = convertView
        }

        try {
            if (fieldId === 0) {
                //  If no custom field is assigned, assume the whole resource is a TextView
                text = view as TextView
            } else {
                //  Otherwise, find the TextView field within the layout
                text = view.findViewById(fieldId)

                if (text == null) {
                    throw RuntimeException("Failed to find view with ID "
                            + context.getResources().getResourceName(fieldId)
                            + " in item layout")
                }
            }
        } catch (e: ClassCastException) {
            Log.e("ArrayAdapter", "You must supply a resource ID for a TextView")
            throw IllegalStateException(
                    "ArrayAdapter requires the resource ID to be a TextView", e)
        }

        val item = getItem(position)
        if (item is CharSequence) {
            text.text = item
        } else {
            text.text = item!!.toString()
        }

        return view
    }