Прядильщик с пустым выбором

Я пытаюсь создать spinner с пустым выбором, но на самом деле он отображает первый элемент из вариантов spinner. Если я добавлю нулевое значение в свою строку, которая является источником выбора в spinner, то после открытия spinner откроется эта пустая строка. Как я должен это делать? Вот код, который я использую:

String[] ch= {"Session1","Session2","Session3"}; Spinner sp; TextView sess_name; sp= (Spinner)findViewById(R.id.spinner1); sess_name=(TextView)findViewById(R.id.sessname); ArrayAdapter<String> adapter=new ArrayAdapter<String>(this,android.R.layout.simple_spinner_item,ch); sp.setAdapter(adapter); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); sp.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) { int index = arg0.getSelectedItemPosition(); sess_name.setText(ch[index]); Toast.makeText(getBaseContext(), "You have selected item : " + ch[index], Toast.LENGTH_SHORT).show(); } 

Решение Barak имеет проблемы, когда вы выбираете первый элемент, Spinner не вызывает метод OnItemSelected OnItemSelectedListener и обновляет пустое содержимое, потому что предыдущая позиция и ваша позиция выбора равны 0.

Сначала поместите пустую строку в начало вашего массива строк, например

 String[] test={" ","one","two","three"}; 

Строить adatper, не изменять getView (), изменять getDropDownView (), устанавливать пустую высоту View в 1px

  private class MyArrayAdapter extends ArrayAdapter<String> { private int textViewResourceId; public MyArrayAdapter(Context context, int textViewResourceId, String[] objects) { super(context, textViewResourceId, objects); this.textViewResourceId = textViewResourceId; } @Override public View getDropDownView(int position, View convertView, ViewGroup parent) { View view; TextView text; if (convertView == null) { view = getLayoutInflater().inflate(textViewResourceId, parent, false); } else { view = convertView; } text = (TextView) view; String item; item = getItem(position); text.setText((CharSequence) item); if (position == 0) { ViewGroup.LayoutParams l = text.getLayoutParams(); l.height = 1; text.setLayoutParams(l); } else { ViewGroup.LayoutParams l = text.getLayoutParams(); //you can change height value to yours l.height = 96; text.setLayoutParams(l); } return view; } } 

Я немного опаздываю на вечеринку, но вот что я сделал, чтобы решить эту проблему.
Если пользователь отменяет выбор исходного элемента, счетчик сохранит начальное пустое состояние. Как только начальный элемент был выбран, он работает как «нормальный»,
Работает на 2.3.3+, я не тестировал 2.2 и ниже

Сначала создайте класс адаптера …

 public class EmptyFirstItemAdapter extends ArrayAdapter<String>{ //Track the removal of the empty item private boolean emptyRemoved = false; /** Adjust the constructor(s) to fit your purposes. */ public EmptyFirstitemAdapter(Context context, List<String> objects) { super(context, android.R.layout.simple_spinner_item, objects); setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); } @Override public int getCount() { //Adjust the count based on the removal of the empty item if(emptyRemoved){ return super.getCount(); } return super.getCount()-1; } @Override public View getDropDownView(int position, View convertView, ViewGroup parent) { if(!emptyRemoved){ // Remove the empty item the first time the dropdown is displayed. emptyRemoved = true; // Set to false to prevent auto-selecting the first item after removal. setNotifyOnChange(false); remove(getItem(0)); // Set it back to true for future changes. setNotifyOnChange(true); } return super.getDropDownView(position, convertView, parent); } @Override public long getItemId(int position) { // Adjust the id after removal to keep the id's the same as pre-removal. if(emptyRemoved){ return position +1; } return position; } } 

Вот строковый массив, который я использовал в strings.xml

 <string-array name="my_items"> <item></item> <item>Item 1</item> <item>Item 2</item> </string-array> 

Затем добавьте OnItemSelectedListener в свой Spinner …

 mSpinner = (Spinner) mRootView.findViewById(R.id.spinner); String[] opts = getResources().getStringArray(R.array.my_items); //DO NOT set the entries in XML OR use an array directly, the adapter will get an immutable List. List<String> vals = new ArrayList<String>(Arrays.asList(opts)); final EmptyFirstitemAdapter adapter = new EmptyFirstitemAdapter(getActivity(), vals); mSpinner.setAdapter(adapter); mSpinner.setOnItemSelectedListener(new OnItemSelectedListener() { //Track that we have updated after removing the empty item private boolean mInitialized = false; @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { if(!mInitialized && position == 0 && id == 1){ // User selected the 1st item after the 'empty' item was initially removed, // update the data set to compensate for the removed item. mInitialized = true; adapter.notifyDataSetChanged(); } } @Override public void onNothingSelected(AdapterView<?> parent) { // Nothing to do } }); 

Это может быть не «идеальное» решение, но я надеюсь, что это поможет кому-то.

После некоторого размышления, я считаю, что придумал метод для достижения вашей цели. Он предусматривает создание пользовательского адаптера и установку / поддержание флага для определения того, выбран ли элемент из счетчика. Используя этот метод, вам не нужно создавать / использовать ложные данные (пустая строка).

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

Я создал небольшую примерную программу (код ниже).

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

SpinnerTest.java

 public class SpinnerTestActivity extends Activity { private String[] planets = { "Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune" }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Spinner spinner = (Spinner) findViewById(R.id.spinner); CustomAdapter adapter = new CustomAdapter(this, // Use our custom adapter android.R.layout.simple_spinner_item, planets); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinner.setAdapter(adapter); spinner.setOnItemSelectedListener(new OnItemSelectedListener() { @Override public void onNothingSelected(AdapterView<?> parent) { } @Override public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) { CustomAdapter.flag = true; // Set adapter flag that something has been chosen } }); } } 

CustomAdapter.java

 public class CustomAdapter extends ArrayAdapter { private Context context; private int textViewResourceId; private String[] objects; public static boolean flag = false; public CustomAdapter(Context context, int textViewResourceId, String[] objects) { super(context, textViewResourceId, objects); this.context = context; this.textViewResourceId = textViewResourceId; this.objects = objects; } @Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) convertView = View.inflate(context, textViewResourceId, null); if (flag != false) { TextView tv = (TextView) convertView; tv.setText(objects[position]); } return convertView; } } 

Вы должны положить первый элемент spinner пустым или со string указывающей, что ничего не выбрано так:

 String[] ch= {"","Session1", "Session2", "Session3"}; 

или

 String[] ch= {"Nothing selected", "Session1", "Session2", "Session3"}; 

Надеюсь помочь

Вот что я использую. Он правильно обрабатывает нулевой (пустой) выбор в общем виде. Он работает с любым типом модели T, если класс T правильно реализует toString() , чтобы отобразить текст, показанный на счетчике, и equals() , чтобы элементы могли быть выбраны по ссылке, а не по позиционному индексу.

 package com.10xdev.android.components; import android.content.Context; import android.graphics.Color; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.Spinner; import android.widget.TextView; import java.util.ArrayList; import java.util.List; /** * A spinner where no selection is possible, and other enhancements. * requires model class to properly implement Object.equals, with semantic comparaison (such as id comparaison) * and a proper toString(), whose result will be displayed in the spinner * * @author tony.benbrahim */ public class EnhancedSpinner<T> extends Spinner { private final EnhanceArraySpinnerAdapter<T> spinnerAdapter; private final List<T> items = new ArrayList<>(); private T selected = null; public EnhancedSpinner(final Context context, final AttributeSet attributeSet) { super(context, attributeSet); spinnerAdapter = new EnhanceArraySpinnerAdapter<>(context, items); setAdapter(spinnerAdapter); } /** * sets the items to be displayed * * @param items */ public void setItems(final List<T> items) { this.items.clear(); //very iffy, but works because of type erasure this.items.add((T) ""); this.items.addAll(items); spinnerAdapter.notifyDataSetChanged(); updateSelected(); } /** * set the selected item. this may be called before or after setting items * * @param item the item to select, or null to clear the selection */ public void setSelected(final T item) { this.selected = item; updateSelected(); } /** * gets the selected item, or null if no item is selected * * @return */ @Override public T getSelectedItem() { return getSelectedItemPosition() != 0 ? (T) super.getSelectedItem() : null; } /** * set the error message for the select * * @param errorMessage */ public void setError(final String errorMessage) { final TextView errorText = (TextView) getSelectedView(); errorText.setError("error"); errorText.setTextColor(Color.RED); errorText.setText(errorMessage); } private void updateSelected() { if (selected == null) { setSelection(0); } else { for (int i = 1; i < items.size(); ++i) { if (selected.equals(items.get(i))) { setSelection(i); break; } } } } private class EnhanceArraySpinnerAdapter<T> extends ArrayAdapter<T> { private final LayoutInflater inflater; public EnhanceArraySpinnerAdapter(final Context context, final List<T> objects) { super(context, android.R.layout.simple_spinner_item, objects); inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); } @Override public View getDropDownView(final int position, final View convertView, final ViewGroup parent) { final TextView textView = convertView != null ? (TextView) convertView : (TextView) inflater.inflate(android.R.layout.simple_spinner_item, parent, false); final Object item = getItem(position); textView.setText(item.toString()); final ViewGroup.LayoutParams layoutParams = textView.getLayoutParams(); layoutParams.height = position == 0 ? 1 : LayoutParams.WRAP_CONTENT; textView.setLayoutParams(layoutParams); return textView; } } }