Cómo hacer un Android Spinner con el texto inicial “Select One”

En Android, quiero utilizar un Spinner que inicialmente (cuando el usuario aún no ha hecho una selección) muestra el texto “Seleccionar uno”. Cuando el usuario hace clic en la rueda giratoria, se muestra la lista de elementos y el usuario selecciona una de las opciones. Después de que el usuario haya hecho una selección, el elemento seleccionado se muestra en el Spinner en lugar de “Seleccionar uno”.

Tengo el siguiente código para crear un Spinner:

String[] items = new String[] {"One", "Two", "Three"}; Spinner spinner = (Spinner) findViewById(R.id.mySpinner); ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_spinner_item, items); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinner.setAdapter(adapter); 

Con este código, inicialmente se muestra el ítem “Uno”. Podría simplemente agregar un nuevo elemento “Seleccionar uno” a los artículos, pero luego “Seleccionar uno” también se mostraría en la lista desplegable como primer elemento, que no es lo que quiero.

¿Como puedo solucionar este problema?

Aquí hay una solución general que anula la vista de Spinner . setAdapter() para establecer la posición inicial en -1 y proxies el SpinnerAdapter suministrado para mostrar la cadena de solicitud para una posición menor que 0.

Esto ha sido probado en Android 1.5 a 4.2, ¡pero cuidado con el comprador! Debido a que esta solución se basa en la reflexión para llamar a la AdapterView.setNextSelectedPositionInt() privada AdapterView.setNextSelectedPositionInt() y AdapterView.setSelectedPositionInt() , no se garantiza que funcione en futuras actualizaciones del sistema operativo. Parece probable que así sea, pero de ninguna manera está garantizado.

Normalmente, no toleraría algo como esto, pero esta pregunta se me ha formulado suficientes veces y parece una solicitud lo suficientemente razonable como para pensar que publicaría mi solución.

 /** * A modified Spinner that doesn't automatically select the first entry in the list. * * Shows the prompt if nothing is selected. * * Limitations: does not display prompt if the entry list is empty. */ public class NoDefaultSpinner extends Spinner { public NoDefaultSpinner(Context context) { super(context); } public NoDefaultSpinner(Context context, AttributeSet attrs) { super(context, attrs); } public NoDefaultSpinner(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override public void setAdapter(SpinnerAdapter orig ) { final SpinnerAdapter adapter = newProxy(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); } } protected SpinnerAdapter newProxy(SpinnerAdapter obj) { return (SpinnerAdapter) java.lang.reflect.Proxy.newProxyInstance( obj.getClass().getClassLoader(), new Class[]{SpinnerAdapter.class}, new SpinnerAdapterProxy(obj)); } /** * Intercepts getView() to display the prompt if position < 0 */ protected class SpinnerAdapterProxy implements InvocationHandler { protected SpinnerAdapter obj; protected Method getView; protected SpinnerAdapterProxy(SpinnerAdapter obj) { this.obj = obj; try { this.getView = SpinnerAdapter.class.getMethod( "getView",int.class,View.class,ViewGroup.class); } catch( Exception e ) { throw new RuntimeException(e); } } public Object invoke(Object proxy, Method m, Object[] args) throws Throwable { try { return m.equals(getView) && (Integer)(args[0])<0 ? getView((Integer)args[0],(View)args[1],(ViewGroup)args[2]) : m.invoke(obj, args); } catch (InvocationTargetException e) { throw e.getTargetException(); } catch (Exception e) { throw new RuntimeException(e); } } protected View getView(int position, View convertView, ViewGroup parent) throws IllegalAccessException { if( position<0 ) { final TextView v = (TextView) ((LayoutInflater)getContext().getSystemService( Context.LAYOUT_INFLATER_SERVICE)).inflate( android.R.layout.simple_spinner_item,parent,false); v.setText(getPrompt()); return v; } return obj.getView(position,convertView,parent); } } } 

Lo que puedes hacer es decorar tu SpinnerAdapter con uno que presente una opción ‘Seleccionar opción …’ inicialmente para que el Spinner se muestre sin nada seleccionado.

Aquí hay un ejemplo de trabajo probado para Android 2.3 y 4.0 (no usa nada en la biblioteca de compatibilidad, por lo que debería estar bien por un tiempo). Como es un decorador, debería ser fácil CursorLoader código existente y funciona bien también con CursorLoader . . (Cambie el cursor en el cursor envuelto cursorAdapter por supuesto …)

Hay un error de Android que hace que sea un poco más difícil volver a utilizar las vistas. (Por lo tanto, debe usar setTag o alguna otra cosa para asegurarse de que su convertView sea ​​correcto). Spinner no es compatible con múltiples tipos de vistas

Notas de código: 2 constructores

Esto le permite usar un aviso estándar o definir su propio ‘nada seleccionado’ como la primera fila, o ambas, o ninguna. (Nota: algunos temas muestran un DropDown para un Spinner en lugar de un diálogo. El menú desplegable normalmente no muestra el mensaje)

Usted define un diseño para ‘mirar’ como un aviso, por ejemplo, atenuado …

Inicial nada seleccionado

Usando un prompt estándar (aviso de que no hay nada seleccionado):

Con una solicitud estándar

O con un mensaje y algo dynamic (tampoco podría haber recibido un aviso):

Inducido y nada seleccionado fila

Uso en el ejemplo anterior

 Spinner spinner = (Spinner) findViewById(R.id.spinner); ArrayAdapter adapter = ArrayAdapter.createFromResource(this, R.array.planets_array, android.R.layout.simple_spinner_item); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinner.setPrompt("Select your favorite Planet!"); spinner.setAdapter( new NothingSelectedSpinnerAdapter( adapter, R.layout.contact_spinner_row_nothing_selected, // R.layout.contact_spinner_nothing_selected_dropdown, // Optional this)); 

contact_spinner_row_nothing_selected.xml

   

NothingSelectedSpinnerAdapter.java

 import android.content.Context; import android.database.DataSetObserver; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ListAdapter; import android.widget.SpinnerAdapter; /** * Decorator Adapter to allow a Spinner to show a 'Nothing Selected...' initially * displayed instead of the first choice in the Adapter. */ public class NothingSelectedSpinnerAdapter implements SpinnerAdapter, ListAdapter { protected static final int EXTRA = 1; protected SpinnerAdapter adapter; protected Context context; protected int nothingSelectedLayout; protected int nothingSelectedDropdownLayout; protected LayoutInflater layoutInflater; /** * Use this constructor to have NO 'Select One...' item, instead use * the standard prompt or nothing at all. * @param spinnerAdapter wrapped Adapter. * @param nothingSelectedLayout layout for nothing selected, perhaps * you want text grayed out like a prompt... * @param context */ public NothingSelectedSpinnerAdapter( SpinnerAdapter spinnerAdapter, int nothingSelectedLayout, Context context) { this(spinnerAdapter, nothingSelectedLayout, -1, context); } /** * Use this constructor to Define your 'Select One...' layout as the first * row in the returned choices. * If you do this, you probably don't want a prompt on your spinner or it'll * have two 'Select' rows. * @param spinnerAdapter wrapped Adapter. Should probably return false for isEnabled(0) * @param nothingSelectedLayout layout for nothing selected, perhaps you want * text grayed out like a prompt... * @param nothingSelectedDropdownLayout layout for your 'Select an Item...' in * the dropdown. * @param context */ public NothingSelectedSpinnerAdapter(SpinnerAdapter spinnerAdapter, int nothingSelectedLayout, int nothingSelectedDropdownLayout, Context context) { this.adapter = spinnerAdapter; this.context = context; this.nothingSelectedLayout = nothingSelectedLayout; this.nothingSelectedDropdownLayout = nothingSelectedDropdownLayout; layoutInflater = LayoutInflater.from(context); } @Override public final View getView(int position, View convertView, ViewGroup parent) { // This provides the View for the Selected Item in the Spinner, not // the dropdown (unless dropdownView is not set). if (position == 0) { return getNothingSelectedView(parent); } return adapter.getView(position - EXTRA, null, parent); // Could re-use // the convertView if possible. } /** * View to show in Spinner with Nothing Selected * Override this to do something dynamic... eg "37 Options Found" * @param parent * @return */ protected View getNothingSelectedView(ViewGroup parent) { return layoutInflater.inflate(nothingSelectedLayout, parent, false); } @Override public View getDropDownView(int position, View convertView, ViewGroup parent) { // Android BUG! http://code.google.com/p/android/issues/detail?id=17128 - // Spinner does not support multiple view types if (position == 0) { return nothingSelectedDropdownLayout == -1 ? new View(context) : getNothingSelectedDropdownView(parent); } // Could re-use the convertView if possible, use setTag... return adapter.getDropDownView(position - EXTRA, null, parent); } /** * Override this to do something dynamic... For example, "Pick your favorite * of these 37". * @param parent * @return */ protected View getNothingSelectedDropdownView(ViewGroup parent) { return layoutInflater.inflate(nothingSelectedDropdownLayout, parent, false); } @Override public int getCount() { int count = adapter.getCount(); return count == 0 ? 0 : count + EXTRA; } @Override public Object getItem(int position) { return position == 0 ? null : adapter.getItem(position - EXTRA); } @Override public int getItemViewType(int position) { return 0; } @Override public int getViewTypeCount() { return 1; } @Override public long getItemId(int position) { return position >= EXTRA ? adapter.getItemId(position - EXTRA) : position - EXTRA; } @Override public boolean hasStableIds() { return adapter.hasStableIds(); } @Override public boolean isEmpty() { return adapter.isEmpty(); } @Override public void registerDataSetObserver(DataSetObserver observer) { adapter.registerDataSetObserver(observer); } @Override public void unregisterDataSetObserver(DataSetObserver observer) { adapter.unregisterDataSetObserver(observer); } @Override public boolean areAllItemsEnabled() { return false; } @Override public boolean isEnabled(int position) { return position != 0; // Don't allow the 'nothing selected' // item to be picked. } } 

Terminé usando un Button lugar. Mientras que un Button no es un Spinner , el comportamiento es fácil de personalizar.

Primero crea el adaptador como de costumbre:

 String[] items = new String[] {"One", "Two", "Three"}; ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_spinner_dropdown_item, items); 

Tenga en cuenta que estoy usando el simple_spinner_dropdown_item como el ID de diseño. Esto ayudará a crear una mejor apariencia al crear el diálogo de alerta.

En el controlador onClick para mi botón tengo:

 public void onClick(View w) { new AlertDialog.Builder(this) .setTitle("the prompt") .setAdapter(adapter, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // TODO: user specific action dialog.dismiss(); } }).create().show(); } 

¡Y eso es!

Sé que esta pregunta tiene muchas respuestas, pero encontré la manera más simple y fácil de hacerlo.

Esta solución es independiente del nivel de API, funcionará para todos los niveles de API .

Idea es establecer el último elemento de la ruleta como uno predeterminado …

 spinner.setSelection(lastIndex);//index starts from 0.so if spinner has 5 item the lastIndex is 4 

El ítem en el último índice debe ser su Título de spinner como “Seleccionar país”

Y mientras se rellena el control numérico, se reduce el conteo del elemento en uno. // El recuento comienza de 1 a elemento total.

  @Override public int getCount() { // don't display last item. It is used as hint. int count = super.getCount(); return count > 0 ? count - 1 : count; } 

Entonces su flujo de código será así

 List objects = new ArrayList(); objects.add("India"); objects.add("Pakistan"); objects.add("China"); // add hint as last item objects.add("Select Country"); HintAdapter adapter = new HintAdapter(context, objects, android.R.layout.simple_spinner_item); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); Spinner spinnerFilmType = (Spinner) findViewById(R.id.spinner); spinner.setAdapter(adapter); // show hint spinner.setSelection(adapter.getCount()); 

HintAdapter.java

  public class HintAdapter extends ArrayAdapter { public HintAdapter(Context theContext, List objects, int theLayoutResId) { super(theContext, theLayoutResId, objects); } @Override public int getCount() { // don't display last item. It is used as hint. int count = super.getCount(); return count > 0 ? count - 1 : count; } } 

Título de Spinner Título de Spinner Artículo Spinner Artículos Spinner

EDITAR: error tipográfico

En primer lugar, es posible que le interese el atributo prompt de la clase Spinner . Vea la imagen a continuación, “Elegir un planeta” es el mensaje que se puede configurar en el XML con android:prompt="" .

enter image description here

Iba a sugerir subclases a Spinner , donde podías mantener dos adaptadores internamente. Un adaptador que tiene la opción “Seleccionar uno” y el otro adaptador real (con las opciones reales), luego utiliza OnClickListener para cambiar los adaptadores antes de que se muestre el cuadro de diálogo de opciones. Sin embargo, después de intentar implementar esa idea, he llegado a la conclusión de que no puedes recibir eventos OnClick para el widget en sí.

Podría envolver la ruleta en una vista diferente, interceptar los clics en la vista y luego decirle a su CustomSpinner que cambie el adaptador, pero parece un truco horrible.

¿De verdad necesitas mostrar “Seleccionar uno”?

Este código ha sido probado y funciona en Android 4.4

enter image description here

 Spinner spinner = (Spinner) activity.findViewById(R.id.spinner); ArrayAdapter adapter = new ArrayAdapter(activity, android.R.layout.simple_spinner_dropdown_item) { @Override public View getView(int position, View convertView, ViewGroup parent) { View v = super.getView(position, convertView, parent); if (position == getCount()) { ((TextView)v.findViewById(android.R.id.text1)).setText(""); ((TextView)v.findViewById(android.R.id.text1)).setHint(getItem(getCount())); //"Hint to be displayed" } return v; } @Override public int getCount() { return super.getCount()-1; // you dont display last item. It is used as hint. } }; adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); adapter.add("Daily"); adapter.add("Two Days"); adapter.add("Weekly"); adapter.add("Monthly"); adapter.add("Three Months"); adapter.add("HINT_TEXT_HERE"); //This is the text that will be displayed as hint. spinner.setAdapter(adapter); spinner.setSelection(adapter.getCount()); //set the hint the default selection so it appears on launch. spinner.setOnItemSelectedListener(this); 

Encontré esta solución:

 String[] items = new String[] {"Select One", "Two", "Three"}; Spinner spinner = (Spinner) findViewById(R.id.mySpinner); ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_spinner_item, items); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinner.setAdapter(adapter); spinner.setOnItemSelectedListener(new OnItemSelectedListener() { @Override public void onItemSelected(AdapterView arg0, View arg1, int position, long id) { items[0] = "One"; selectedItem = items[position]; } @Override public void onNothingSelected(AdapterView arg0) { } }); 

Simplemente cambie la matriz [0] con “Seleccionar una” y luego en onItemSelected, cambie el nombre a “One”.

No es una solución elegante, pero funciona: D

No hay una API predeterminada para establecer la sugerencia en Spinner. Para agregarlo, necesitamos una pequeña solución sin la implementación de la reflexión de seguridad

 List objects = new ArrayList(); objects.add(firstItem); objects.add(secondItem); // add hint as last item objects.add(hint); HintAdapter adapter = new HintAdapter(context, objects, android.R.layout.simple_spinner_item); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); Spinner spinnerFilmType = (Spinner) findViewById(R.id.spinner); spinner.setAdapter(adapter); // show hint spinner.setSelection(adapter.getCount()); 

Fuente del adaptador:

 public class HintAdapter extends ArrayAdapter { public HintAdapter(Context theContext, List objects) { super(theContext, android.R.id.text1, android.R.id.text1, objects); } public HintAdapter(Context theContext, List objects, int theLayoutResId) { super(theContext, theLayoutResId, android.R.id.text1, objects); } @Override public int getCount() { // don't display last item. It is used as hint. int count = super.getCount(); return count > 0 ? count - 1 : count; } } 

Fuente original

Muchas respuestas aquí, pero estoy sorprendido de que nadie sugiriera una solución simple: coloque un TextView sobre el Spinner. Establezca un oyente de clic en el TextView que oculta el TextView muestra el Spinner y llama a spinner.performClick ().

Tengo el mismo problema para spinner, con una selección vacía, y encontré una mejor solución. Echa un vistazo a este código simple.

 Spinner lCreditOrDebit = (Spinner)lCardPayView.findViewById(R.id.CARD_TYPE); spinneradapter lAdapter = new spinneradapter( BillPayScreen.this, ndroid.R.layout.simple_spinner_item,getResources().getStringArray(R.array.creditordebit)); lAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); lCreditOrDebit.setAdapter(lAdapter); 

Aquí spinneradapter es una pequeña personalización para arrayadapter. Se parece a esto:

 import android.content.Context; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.ImageView; public class spinneradapter extends ArrayAdapter{ private Context m_cContext; public spinneradapter(Context context,int textViewResourceId, String[] objects) { super(context, textViewResourceId, objects); this.m_cContext = context; } boolean firsttime = true; @Override public View getView(int position, View convertView, ViewGroup parent) { if(firsttime){ firsttime = false; //Just return some empty view return new ImageView(m_cContext); } //Let the array adapter take care of it this time. return super.getView(position, convertView, parent); } } 

Archivo XML:

  

Actividad:

 private Spinner featuresSelection; private ArrayAdapter featuresAdapter; private List featuresList; 

onCreate:

 featuresList = new ArrayList(); featuresAdapter = new ArrayAdapter(this, android.R.layout.simple_spinner_item, featuresList); featuresAdapter.setDropDownViewResource( android.R.layout.simple_spinner_dropdown_item); featuresSelection = ((Spinner) yourActivity.this .findViewById(R.id.locationSpinner)); featuresSelection.setAdapter(featuresAdapter); featuresSelection.setOnItemSelectedListener( new MyOnItemSelectedListener()); 

Algunas funciones (agregue cosas al adaptador mediante progtwigción)>

 featuresAdapter.add("some string"); 

Ahora tiene un spinner vacío y puede escribir código para no abrir el diálogo si está vacío. O pueden presionar hacia atrás. Pero también lo rellena con una función u otra lista durante el tiempo de ejecución.

Puede cambiarlo a una vista de texto y usar esto:

 android:style="@android:style/Widget.DeviceDefault.Light.Spinner" 

y luego defina la propiedad android:text .

Lo intenté como lo siguiente. Toma un botón y dale el evento click. Al cambiar el fondo del botón, parece ser un spinner.

Declarar como variables globales alertdialog y valor predeterminado ..

 AlertDialog d; static int default_value = 0; final Button btn = (Button) findViewById(R.id.button1); btn .setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //c.show(); final CharSequence str[] = {"Android","Black Berry","Iphone"}; AlertDialog.Builder builder = new AlertDialog.Builder(TestGalleryActivity.this).setSingleChoiceItems( str, default_value,new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int position) { Toast.makeText(TestGalleryActivity.this, "" + position, Toast.LENGTH_SHORT).show(); default_value = position; btn.setText(str[position]); if(d.isShowing()) d.dismiss(); } }).setTitle("Select Any"); d = builder.create(); d.show(); } }); 

Eche un vistazo a la aplicación iosched para una solución de propósito general para agregar un elemento al principio de una lista. En particular, si está utilizando un CursorAdapter, mire TracksAdapter.java que amplía esa definición para proporcionar un método “setHasAllItem” y el código asociado para administrar el recuento de listas para tratar con el elemento adicional en la parte superior.

Con el adaptador personalizado, puede configurar el texto como “Seleccionar uno” o cualquier otra cosa que desee que diga ese elemento principal.

Tengo un spinner en mi main.xml y su id es @+id/spinner1

esto es lo que escribo en mi función OnCreate:

 spinner1 = (Spinner)this.findViewById(R.id.spinner1); final String[] groupes = new String[] {"A", "B", "C", "D", "E", "F", "G", "H"}; ArrayAdapter featuresAdapter = new ArrayAdapter(this, android.R.layout.simple_spinner_item, new ArrayList()); featuresAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinner1.setAdapter(featuresAdapter); for (String s : groupes) featuresAdapter.add(s); spinner1.setOnItemSelectedListener(new OnItemSelectedListener() { public void onItemSelected(AdapterView arg0, View arg1, int position, long id) { // Here go your instructions when the user chose something Toast.makeText(getBaseContext(), groupes[position], 0).show(); } public void onNothingSelected(AdapterView arg0) { } }); 

No necesita ninguna implementación en la clase.

Creo que la manera más fácil es crear un ítem ficticio en el índice 0 diciendo “seleccionar uno” y luego guardarlo, tal vez verificar que la selección no sea 0.

Así que este es mi ejemplo final “all-in” para un botón-spinner

En activity_my_form.xml

   

En strings.xml

 Select planet…  The Sun with a name very long so long long long long longThe Sun with a name very long so long long long long longThe Sun with a name very long so long long long long long Mercury Venus Earth Mars Jupiter Saturn Uranus Neptune  

En MyFormActivity.java

 public class MyFormActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { ((Button) findViewById(R.id.btnSpinnerPlanets)).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { final String[] items = view.getResources().getStringArray(R.array.planets__entries); ArrayAdapter adapter = new ArrayAdapter(MyFormActivity.this, android.R.layout.simple_spinner_dropdown_item, items); new AlertDialog.Builder(MyFormActivity.this).setTitle("the prompt").setAdapter(adapter, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { ((Button) findViewById(R.id.btnSpinnerPlanets)).setText(items[which]); dialog.dismiss(); } }).create().show(); } }); } } 

Finalmente obtuve un tamaño de letra configurable sin primer elemento seleccionable botón spinner !!! Gracias a HRJ

Encontré muchas buenas soluciones para esto. la mayoría funciona añadiendo un elemento al final del adaptador y no muestra el último elemento en la lista desplegable. El gran problema para mí fue que la lista desplegable de spinner comenzará desde el final de la lista. Para que el usuario vea los últimos elementos en lugar de los primeros (en caso de tener muchos elementos para mostrar), toque la rueda giratoria por primera vez.

Así que puse el elemento de sugerencia al principio de la lista. y esconde el primer elemento en la lista desplegable.

 private void loadSpinner(){ HintArrayAdapter hintAdapter = new HintArrayAdapter(context, 0); hintAdapter.add("Hint to be displayed"); hintAdapter.add("Item 1"); hintAdapter.add("Item 2"); . . hintAdapter.add("Item 30"); spinner1.setAdapter(hintAdapter); //spinner1.setSelection(0); //display hint. Actually you can ignore it, because the default is already 0 //spinner1.setSelection(0, false); //use this if don't want to onItemClick called for the hint spinner1.setOnItemSelectedListener(yourListener); } private class HintArrayAdapter extends ArrayAdapter { Context mContext; public HintArrayAdapter(Context context, int resource) { super(context, resource); this.mContext = context } @Override public View getView(int position, View convertView, ViewGroup parent) { LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Activity.LAYOUT_INFLATER_SERVICE); View view = inflater.inflate(android.R.layout.simple_spinner_item, parent, false); TextView texview = (TextView) view.findViewById(android.R.id.text1); if(position == 0) { texview.setText(""); texview.setHint(getItem(position).toString()); //"Hint to be displayed" } else { texview.setText(getItem(position).toString()); } return view; } @Override public View getDropDownView(int position, View convertView, ViewGroup parent) { LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Activity.LAYOUT_INFLATER_SERVICE); View view; if(position == 0){ view = inflater.inflate(R.layout.spinner_hint_list_item_layout, parent, false); // Hide first row } else { view = inflater.inflate(android.R.layout.simple_spinner_dropdown_item, parent, false); TextView texview = (TextView) view.findViewById(android.R.id.text1); texview.setText(getItem(position).toString()); } return view; } } 

set the below layout in @Override getDropDownView() when position is 0, to hide the first hint row.

R.layout.spinner_hint_list_item_layout:

    

This is my way:

 List list = new ArrayList(); list.add("string1"); list.add("string2"); list.add("string3"); list.add("[Select one]"); final int listsize = list.size() - 1; ArrayAdapter dataAdapter = new ArrayAdapter(this,android.R.layout.simple_spinner_item, list) { @Override public int getCount() { return(listsize); // Truncate the list } }; dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); mySpinner.setAdapter(dataAdapter); mySpinner.setSelection(listsize); // Hidden item to appear in the spinner 

When extending SpinnerAdapter , you override two View -producing methods, getView(int, View, ViewGroup) and getDropDownView(int, View, ViewGroup) . The first one supplies the View inserted into the Spinner itself; the second supplies the View in the drop-down list (as the name suggests). You can override the getView(...) so that, until an item has been selected, it displays a TextView containing a prompt; then, when you detect an item has been selected, you change it to display a TextView corresponding to that.

 public class PromptingAdapter extends SpinnerAdapter { //... various code ... private boolean selectionmade = false; //call this method from the OnItemSelectedListener for your Spinner public setSelectionState(boolean b) { selectionmade = b; } @Override public View getView(int position, View recycle, ViewGroup container) { if(selectionmade) { //your existing code to supply a View for the Spinner //you could even put "return getDropDownView(position, recycle, container);" } else { View output; if(recycle instanceof TextView) { output = recycle; } else { output = new TextView(); //and layout stuff } output.setText(R.string.please_select_one); //put a string "please_select_one" in res/values/strings.xml return output; } } //... } 

For those using Xamarin, here is the C# equivalent to aaronvargas’s answer above.

 using Android.Content; using Android.Database; using Android.Views; using Android.Widget; using Java.Lang; namespace MyNamespace.Droid { public class NothingSelectedSpinnerAdapter : BaseAdapter, ISpinnerAdapter, IListAdapter { protected static readonly int EXTRA = 1; protected ISpinnerAdapter adapter; protected Context context; protected int nothingSelectedLayout; protected int nothingSelectedDropdownLayout; protected LayoutInflater layoutInflater; public NothingSelectedSpinnerAdapter(ISpinnerAdapter spinnerAdapter, int nothingSelectedLayout, Context context) : this(spinnerAdapter, nothingSelectedLayout, -1, context) { } public NothingSelectedSpinnerAdapter(ISpinnerAdapter spinnerAdapter, int nothingSelectedLayout, int nothingSelectedDropdownLayout, Context context) { this.adapter = spinnerAdapter; this.context = context; this.nothingSelectedLayout = nothingSelectedLayout; this.nothingSelectedDropdownLayout = nothingSelectedDropdownLayout; layoutInflater = LayoutInflater.From(context); } protected View GetNothingSelectedView(ViewGroup parent) { return layoutInflater.Inflate(nothingSelectedLayout, parent, false); } protected View GetNothingSelectedDropdownView(ViewGroup parent) { return layoutInflater.Inflate(nothingSelectedDropdownLayout, parent, false); } public override Object GetItem(int position) { return position == 0 ? null : adapter.GetItem(position - EXTRA); } public override long GetItemId(int position) { return position >= EXTRA ? adapter.GetItemId(position - EXTRA) : position - EXTRA; } public override View GetView(int position, View convertView, ViewGroup parent) { // This provides the View for the Selected Item in the Spinner, not // the dropdown (unless dropdownView is not set). if (position == 0) { return GetNothingSelectedView(parent); } // Could re-use the convertView if possible. return this.adapter.GetView(position - EXTRA, null, parent); } public override int Count { get { int count = this.adapter.Count; return count == 0 ? 0 : count + EXTRA; } } public override View GetDropDownView(int position, View convertView, ViewGroup parent) { // Android BUG! http://code.google.com/p/android/issues/detail?id=17128 - // Spinner does not support multiple view types if (position == 0) { return nothingSelectedDropdownLayout == -1 ? new View(context) : GetNothingSelectedDropdownView(parent); } // Could re-use the convertView if possible, use setTag... return adapter.GetDropDownView(position - EXTRA, null, parent); } public override int GetItemViewType(int position) { return 0; } public override int ViewTypeCount => 1; public override bool HasStableIds => this.adapter.HasStableIds; public override bool IsEmpty => this.adapter.IsEmpty; public override void RegisterDataSetObserver(DataSetObserver observer) { adapter.RegisterDataSetObserver(observer); } public override void UnregisterDataSetObserver(DataSetObserver observer) { adapter.UnregisterDataSetObserver(observer); } public override bool AreAllItemsEnabled() { return false; } public override bool IsEnabled(int position) { return position > 0; } } } 

I also solved this problem by using the following code. Suppose you are having a list of items eg

 ArrayList itemsArrayList = new ArrayList(); Item item1 = new Item(); item1.setId(1); item1.setData("First Element"); Item item2 = new Item(); item2.setId(2); Item2.setData("Second Element"); itemsArrayList.add(item1); itemsArrayList.add(item2); 

Now we have to provide the strings to spinner because spinner can not understand the object. So we will create an new array list with string items like this ->

 ArrayList itemStringArrayList = new ArrayList(); for(Item item : itemsArrayList) { itemStringArrayList.add(item.getData()); } 

Now we have itemStringArrayList array list with two string items. And we have to show the “Select Item” text as first item. So we have to insert an new string into the itemStringArrayList .

 itemStringArrayList.add("Select Item"); 

Now we have an array list itemsArrayList and we want to show two elements in the drop down. But the condition here is …If we don’t select anything then Select Item should appear as first element which will not be enabled.

So we can implement this functionality like this. If you need to load the array list items into the android spinner. So you will have to use some adapter. So here i’ll use the ArrayAdapter . We can use the customise adapter too.

 ArrayAdapter itemsArrayAdapter = new ArrayAdapter(getApplicationContext(), R.layout.spinner_item, itemsArrayList){ @Override public boolean isEnabled(int position) { if(position == 0) { return false; } else { return true; } } @Override public View getDropDownView(int position, View convertView, ViewGroup parent) { View view = super.getDropDownView(position, convertView, parent); TextView tv = (TextView) view; if(position == 0){ // Set the hint text color gray tv.setTextColor(Color.GRAY); } else { tv.setTextColor(Color.BLACK); } return view; } }; itemsArrayAdapter.setDropDownViewResource(R.layout.spinner_item); your_spinner_name.setAdapter(itemsArrayAdapter); 

Here in this code. we are using the customised spinner layout ie R.layout.spinner_item . It’s a simple text view

   

We need to disable the first text in the spinner. So for the position 0 we are disabling the text. And color also we can set by overiding getDropDownView method. So in this way we will get the expected spinner.

I’d just use a RadioGroup with RadioButtons if you only have three choices, you can make them all unchecked at first.

None of the previously submitted answers really worked the way I wanted to solve this issue. To me the ideal solution would provide the “Select One” (or whatever initial text) when the spinner is first displayed. When the user taps the spinner, the initial text shouldn’t be a part of the drop down that is displayed.

To further complicate my particular situation, my spinner data is coming form a cursor that is loaded via the LoaderManager callbacks.

After considerable experimentation I came up with the following solution:

 public class MyFragment extends Fragment implements LoaderManager.LoaderCallbacks{ private static final String SPINNER_INIT_VALUE = "Select A Widget"; private Spinner mSpinner; private int mSpinnerPosition; private boolean mSpinnerDropDownShowing = false; private View mSpinnerDropDown; private MyCursorAdapter mCursorAdapter; ... @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){ ... mCursorAdapter = new MyCursorAdapter(getActivity()); mSpinner = (Spinner) rootView.findViewById(R.id.theSpinner); mSpinner.setOnTouchListener(mSpinnerTouchListener); mSpinner.setAdapter(mCursorAdapter); ... } //Capture the touch events to toggle the spinner's dropdown visibility private OnTouchListener mSpinnerTouchListener = new View.OnTouchListener() { @Override public boolean onTouch(View view, MotionEvent motionEvent) { if(mSpinnerDropDown != null && mSpinnerDropDownShowing == false){ mSpinnerDropDownShowing = true; mSpinnerDropDown.setVisibility(View.VISIBLE); } return false; } }; //Capture the click event on the spinner drop down items protected OnClickListener spinnerItemClick = new OnClickListener(){ @Override public void onClick(View view) { String widget = ((TextView) view.findViewById(android.R.id.text1)).getText().toString(); if(!widget.equals(SPINNER_INIT_VALUE)){ if(mCursorAdapter != null){ Cursor cursor = mCursorAdapter.getCursor(); if(cursor.moveToFirst()){ while(!cursor.isAfterLast()){ if(widget.equals(cursor.getString(WidgetQuery.WIDGET_NAME))){ ... //Set the spinner to the correct item mSpinnerPosition = cursor.getPosition() + 1; mSpinner.setSelection(mSpinnerPosition); break; } cursor.moveToNext(); } } } } //Hide the drop down. Not the most elegent solution but it is the only way I could hide/dismiss the drop down mSpinnerDropDown = view.getRootView(); mSpinnerDropDownShowing = false; mSpinnerDropDown.setVisibility(View.GONE); } }; private class MyCursorAdapter extends CursorAdapter { private final int DISPLACEMENT = 1; private final int DEFAULT_ITEM_ID = Integer.MAX_VALUE; private Activity mActivity; public MyCursorAdapter(Activity activity) { super(activity, null, false); mActivity = activity; } //When loading the regular views, inject the defualt item @Override public View getView(int position, View convertView, ViewGroup parent) { if(position == 0){ if(convertView == null){ convertView = mActivity.getLayoutInflater().inflate(R.layout.list_item_widget, parent, false); } return getDefaultItem(convertView); } return super.getView(position - DISPLACEMENT, convertView, parent); } //When loading the drop down views, set the onClickListener for each view @Override public View getDropDownView(int position, View convertView, ViewGroup parent){ View view = super.getDropDownView(position, convertView, parent); view.setOnClickListener(spinnerItemClick); return view; } //The special default item that is being injected private View getDefaultItem(View convertView){ TextView text = (TextView) convertView.findViewById(android.R.id.text1); text.setText(SPINNER_INIT_VALUE); return convertView; } @Override public long getItemId(int position) { if (position == 0) { return DEFAULT_ITEM_ID; } return super.getItemId(position - DISPLACEMENT); } @Override public boolean isEnabled(int position) { return position == 0 ? true : super.isEnabled(position - DISPLACEMENT); } @Override public int getViewTypeCount() { return super.getViewTypeCount() + DISPLACEMENT; } @Override public int getItemViewType(int position) { if (position == 0) { return super.getViewTypeCount(); } return super.getItemViewType(position - DISPLACEMENT); } @Override public View newView(Context context, Cursor cursor, ViewGroup parent) { return mActivity.getLayoutInflater().inflate(R.layout.list_item_widget, parent, false); } @Override public void bindView(View view, Context context, Cursor cursor){ if(cursor.isAfterLast()){ return; } TextView text = (TextView) view.findViewById(android.R.id.text1); String WidgetName = cursor.getString(WidgetQuery.WIDGET_NAME); text.setText(WidgetName); } } } 

I handle this by using a button instead of a Spinner. I have the sample project up on GitHub.

In the project, i’m displaying both the Spinner and button to show that they indeed look identical. Except the button you can set the initial text to whatever you want.

Here’s what the activity looks like:

 package com.stevebergamini.spinnerbutton; import android.app.Activity; import android.app.AlertDialog; import android.content.DialogInterface; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.Spinner; public class MainActivity extends Activity { Spinner spinner1; Button button1; AlertDialog ad; String[] countries; int selected = -1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); spinner1 = (Spinner) findViewById(R.id.spinner1); button1 = (Button) findViewById(R.id.button1); countries = getResources().getStringArray(R.array.country_names); // You can also use an adapter for the allert dialog if you'd like // ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_spinner_dropdown_item, countries); ad = new AlertDialog.Builder(MainActivity.this).setSingleChoiceItems(countries, selected, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { button1.setText(countries[which]); selected = which; ad.dismiss(); }}).setTitle(R.string.select_country).create(); button1.setOnClickListener( new OnClickListener(){ @Override public void onClick(View v) { ad.getListView().setSelection(selected); ad.show(); }}); } } 

NOTE: Yes, I realize that this is dependent on the applied Theme and the look will be slightly different if using Theme.Holo. However, if you’re using one of the legacy themes such as Theme.Black, you’re good to go.

if you are facing this issue when your items are populates from database-cursor ,

the simplest solution that I found in this SO answer:

use UNION in your cursor adapter query and add the additional item with id= -1 to the query result, without really adding it to the DB:

algo como:

db.rawQuery(“SELECT iWorkerId as _id, nvLastName as name FROM Worker w UNION SELECT -1 as _id , ” as name”,null);

if the item selected is -1, then it’s the default value. Otherwise it’s a record from the table.

Seems a banal solution but I usually put simply a TextView in the front of the spinner. The whole Xml looks like this. (hey guys, don’t shoot me, I know that some of you don’t like this kind of marriage):

     

Then I hide the TextView when an Item was selected. Obviously the background color of the TextView should be the same as the Spinner. Works on Android 4.0. Don’t know on older versions.

Sí. Because the Spinner calls setOnItemSelectedListener at the beginning, the hiding of the textview could be a little bit tricky, but can be done this way:

  Boolean controlTouched; exerciseSpinner.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { controlTouched = true; // I touched it but but not yet selected an Item. return false; } }); exerciseSpinner.setOnItemSelectedListener(new OnItemSelectedListener() { @Override public void onItemSelected(AdapterView arg0, View arg1, int arg2, long arg3) { if (controlTouched) { // Are you sure that I touched it with my fingers and not someone else ? spinnerSelText.setVisibility(View.GONE); } } @Override public void onNothingSelected(AdapterView arg0) { } }); 

for me it worked something like this. has the improvement that only changes the text in SOME options, not in all.

First i take the names of the spinner and create the arrayadapter with a customize view, but it doesn’t matter now, the key is override the getView, and inside change the values u need to change. In my case was only the first one, the rest i leave the original

 public void rellenarSpinnerCompeticiones(){ spinnerArrayCompeticiones = new ArrayList(); for(Competicion c: ((Controlador)getApplication()).getCompeticiones()){ spinnerArrayCompeticiones.add(c.getNombre()); } //ArrayAdapter spinnerArrayAdapter = new ArrayAdapter(this,R.layout.spinner_item_competicion,spinnerArrayCompeticiones); ArrayAdapter spinnerArrayAdapter = new ArrayAdapter(this, R.layout.spinner_item_competicion, spinnerArrayCompeticiones){ @Override public View getView(int position, View convertView, ViewGroup parent) { LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE); final View v = vi.inflate(R.layout.spinner_item_competicion, null); final TextView t = (TextView)v.findViewById(R.id.tvCompeticion); if(spinnerCompeticion.getSelectedItemPosition()>0){ t.setText(spinnerArrayCompeticiones.get(spinnerCompeticion.getSelectedItemPosition())); }else{ t.setText("Competiciones"); } return v; } }; spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinnerCompeticion.setAdapter(spinnerArrayAdapter); } 

here’s a simple one

  private boolean isFirst = true; private void setAdapter() { final ArrayList spinnerArray = new ArrayList(); spinnerArray.add("Select your option"); spinnerArray.add("Option 1"); spinnerArray.add("Option 2"); spin.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView parentView, View selectedItemView, int position, long id) { TextView tv = (TextView)selectedItemView; String res = tv.getText().toString().trim(); if (res.equals("Option 1")) { //do Something } else if (res.equals("Option 2")) { //do Something else } } @Override public void onNothingSelected(AdapterView parentView) { } }); ArrayAdapter adapter = new ArrayAdapter(this, R.layout.my_spinner_style,spinnerArray) { public View getView(int position, View convertView, ViewGroup parent) { View v = super.getView(position, convertView, parent); int height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 25, getResources().getDisplayMetrics()); ((TextView) v).setTypeface(tf2); ((TextView) v).getLayoutParams().height = height; ((TextView) v).setGravity(Gravity.CENTER); ((TextView) v).setTextSize(TypedValue.COMPLEX_UNIT_SP, 19); ((TextView) v).setTextColor(Color.WHITE); return v; } public View getDropDownView(int position, View convertView, ViewGroup parent) { if (isFirst) { isFirst = false; spinnerArray.remove(0); } View v = super.getDropDownView(position, convertView, parent); ((TextView) v).setTextColor(Color.argb(255, 70, 70, 70)); ((TextView) v).setTypeface(tf2); ((TextView) v).setGravity(Gravity.CENTER); return v; } }; spin.setAdapter(adapter); } 

Refer to one of the above answers: https://stackoverflow.com/a/23005376/1312796

I added my code to fix a little bug. That where no data retrieved..How to show the prompt text..!

Here is my Trick…It works fine with me. !

Try to put your spinner in a Relative_layoutand align a Textview with your spinner and play with the visibility of the Textview (SHOW/HIDE) whenever the adapter of the spinner loaded or empty..Like this:

     

Aquí está el código:

  txt__from = (TextView) rootView.findViewById(R.id.txt_prompt_from); 

call this method after and before spinner adapter loaded and empty.

 setPromptTextViewVisibility (); //True or fales public void setPromptTextViewVisibility (boolean visible ) { if (visible) { txt_from.setVisibility(View.VISIBLE); } else { txt_from.setVisibility(View.INVISIBLE); } }