studio not item first color android android-spinner

not - placeholder in spinner android



Cómo hacer un Spinner de Android con texto inicial “Select One” (30)

En Android, quiero usar un Spinner que inicialmente (cuando el usuario aún no ha hecho una selección) muestra el texto "Seleccione uno". Cuando el usuario hace clic en la rueda giratoria, se muestra la lista de elementos y el usuario selecciona una de las opciones. Una vez que el usuario ha realizado 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<String> adapter = new ArrayAdapter<String>(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 elemento "Uno". Simplemente podría agregar un nuevo elemento "Select One" a los elementos, pero luego "Select One" también se mostrará 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 Spinner . setAdapter() para establecer la posición inicial en -1, y proxies el SpinnerAdapter suministrado para mostrar la cadena de solicitud para la posición inferior a 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 AdapterView.setNextSelectedPositionInt() privado y AdapterView.setSelectedPositionInt() , no se garantiza que funcione en futuras actualizaciones del sistema operativo. Parece probable que lo hará, pero de ninguna manera está garantizado.

Normalmente no aprobaría algo como esto, pero esta pregunta se ha formulado suficientes veces y parece una solicitud lo suficientemente razonable como para que pensara en publicar 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); } } }


Archivo XML:

<Spinner android:id="@+id/locationSpinner" android:layout_width="fill_parent" android:layout_height="wrap_content" android:prompt="@string/select_location" />

Actividad:

private Spinner featuresSelection; private ArrayAdapter<CharSequence> featuresAdapter; private List<CharSequence> featuresList;

onCreate:

featuresList = new ArrayList<CharSequence>(); featuresAdapter = new ArrayAdapter<CharSequence>(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 (agregar cosas al adaptador programáticamente)>

featuresAdapter.add("some string");

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


Así que este es mi último ejemplo "all-in" para un botón giratorio

En activity_my_form.xml

<Button android:id="@+id/btnSpinnerPlanets" android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="left|center_vertical" android:singleLine="true" android:text="@string/selectAPlanet" android:textSize="10sp" android:background="@android:drawable/btn_dropdown"> </Button>

En cadenas.xml

<string name="selectAPlanet">Select planet&#8230;</string> <string-array name="planets__entries"> <item>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</item> <item>Mercury</item> <item>Venus</item> <item>Earth</item> <item>Mars</item> <item>Jupiter</item> <item>Saturn</item> <item>Uranus</item> <item>Neptune</item> </string-array>

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<String> adapter = new ArrayAdapter<String>(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 fuente configurable sin botón de selección de primer elemento! Gracias a HRJ


Creo que la forma más sencilla es crear un elemento ficticio en el índice 0 que diga "seleccionar uno" y luego, al guardar, tal vez comprobar que la selección no es 0.


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 extiende esa definición para proporcionar un método "setHasAllItem" y el código asociado para administrar el recuento de la lista para tratar el elemento adicional en la parte superior.

Usando el adaptador personalizado, puede configurar el texto en "Seleccionar uno" o cualquier otra cosa que desee que diga el artículo principal.


En primer lugar, podría interesarle el atributo de prompt de la clase Spinner . Vea la imagen a continuación, "Elija un planeta" es el mensaje que se puede configurar en el XML con android:prompt="" .

Iba a sugerir subclasificar a Spinner , donde se podrían mantener dos adaptadores internamente. Un adaptador que tiene la opción "Seleccionar uno" y el otro adaptador real (con las opciones reales), luego usa el OnClickListener para cambiar los adaptadores antes de que se muestre el diálogo de opciones. Sin embargo, después de intentar implementar esa idea, llegué a la conclusión de que no puede recibir eventos OnClick para el propio widget.

Podría ajustar el control de giro 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.

¿Realmente necesitas mostrar "Select One"?


Encontré esta solución:

String[] items = new String[] {"Select One", "Two", "Three"}; Spinner spinner = (Spinner) findViewById(R.id.mySpinner); ArrayAdapter<String> adapter = new ArrayAdapter<String>(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 uno" y luego en onItemSelected, cambie su nombre a "Uno".

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


Esta es mi manera:

List<String> list = new ArrayList<String>(); list.add("string1"); list.add("string2"); list.add("string3"); list.add("[Select one]"); final int listsize = list.size() - 1; ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>(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


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

Spinner spinner = (Spinner) activity.findViewById(R.id.spinner); ArrayAdapter<String> adapter = new ArrayAdapter<String>(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);


Hay muchas respuestas aquí, pero me sorprende que nadie haya sugerido una solución simple: coloque un TextView encima del Spinner. Establezca un detector de clics en el TextView que oculta el TextView que muestra el Spinner y llama spinner.performClick ().


He intentado como el siguiente. Toma un botón y dale el evento clic. Al cambiar el fondo del botón, parece ser una rueda giratoria.

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


Lo que puede hacer es decorar su SpinnerAdapter con uno que presente una vista de ''Seleccionar opción ...'' inicialmente para que el Spinner se muestre sin nada seleccionado.

Este es 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) Ya que es un decorador, debería ser fácil de modificar el código existente y funciona bien con CursorLoader también . (Cursor de intercambio en el cursor cursorAdapter por supuesto ...)

Hay un error de Android que hace que esto sea un poco más difícil para reutilizar las vistas. (Por lo tanto, debe usar setTag o algo más para asegurarse de que su convertView sea ​​correcto). Spinner no admite varios tipos de vista

Notas de código: 2 constructores

Esto le permite usar un indicador estándar o definir su propio ''nada seleccionado'' como la primera fila, o ambos, o ninguno. (Nota: algunos temas muestran un DropDown para un Spinner en lugar de un cuadro de diálogo. El menú desplegable normalmente no muestra el indicador)

Usted define un diseño para que ''parezca'' un mensaje, por ejemplo, en gris ...

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

O con un prompt y algo dinámico (podría no haber tenido ningún prompt):

Uso en el ejemplo anterior

Spinner spinner = (Spinner) findViewById(R.id.spinner); ArrayAdapter<CharSequence> 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

<?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/text1" style="?android:attr/spinnerItemStyle" android:singleLine="true" android:layout_width="match_parent" android:layout_height="wrap_content" android:ellipsize="marquee" android:textSize="18sp" android:textColor="#808080" android:text="[Select a Planet...]" />

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... e.g. "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. } }


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

List<Object> objects = new ArrayList<Object>(); 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<Objects> { public HintAdapter(Context theContext, List<Object> objects) { super(theContext, android.R.id.text1, android.R.id.text1, objects); } public HintAdapter(Context theContext, List<Object> 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


Puedes cambiarlo a una vista de texto y usar esto:

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

y luego definir la propiedad de android:text .


Sé que esta pregunta tiene muchas respuestas, pero encontré la forma más sencilla y sencilla de hacerlo.

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

La idea es configurar el último elemento del control de giro como 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 giro como "Seleccionar país"

Y mientras llena el control de giro, disminuya la cuenta del elemento en uno. // El conteo comienza desde 1 hasta el 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; }

Así tu flujo de código será así

List<String> objects = new ArrayList<String>(); 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<Objects> { public HintAdapter(Context theContext, List<Object> 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 Spinner Item

EDITAR: Typo


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<CharSequence> featuresAdapter = new ArrayAdapter<CharSequence>(this, android.R.layout.simple_spinner_item, new ArrayList<CharSequence>()); 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.


Terminé usando un Button lugar. Si bien 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<String> adapter = new ArrayAdapter<String>(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!


Tuve 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<String>{ 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); } }


Aquí hay una simple

private boolean isFirst = true; private void setAdapter() { final ArrayList<String> spinnerArray = new ArrayList<String>(); 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<String> adapter = new ArrayAdapter<String>(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); }


Para aquellos que usan Xamarin, aquí está el C # equivalente a la respuesta de aaronvargas anterior.

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


Yo solo usaría un Grupo de Radio con RadioButtons si solo tiene tres opciones, puede hacer que todas estén sin marcar al principio.


Al extender SpinnerAdapter, anulas dos Viewmétodos de producción, getView(int, View, ViewGroup)y getDropDownView(int, View, ViewGroup). El primero suministra lo Viewinsertado en Spinnersí mismo; el segundo lo proporciona Viewen la lista desplegable (como sugiere su nombre). Puede anular la getView(...)opción de modo que, hasta que se haya seleccionado un elemento, muestre TextViewun mensaje que contiene una solicitud; luego, cuando detecta que un elemento ha sido seleccionado, lo cambia para mostrar un TextViewcorrespondiente a eso.

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; } } //... }


Consulte una de las respuestas anteriores: https://.com/a/23005376/1312796

Agregué mi código para arreglar un pequeño error. Allí donde no se recuperan datos ... Cómo mostrar el texto de solicitud ...!

Aquí está mi truco ... Funciona bien conmigo. !

Intente colocar su hilandero en una Relative_layout y alinee una Vista de texto con su girador y juegue con la visibilidad de la Vista de texto (MOSTRAR / OCULTAR) cuando el adaptador del girador esté cargado o vacío.

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:layout_marginTop="20dp" android:background="#ededed" android:orientation="vertical"> <TextView android:id="@+id/txt_prompt_from" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:textColor="@color/gray" android:textSize="16sp" android:layout_alignStart="@+id/sp_from" android:text="From" android:visibility="gone"/> <Spinner android:id="@+id/sp_from" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerVertical="true" />

Aquí está el código:

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

Llama a este método después y antes de que el adaptador del rotor esté cargado y vacío.

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


Encontré muchas buenas soluciones para esto. la mayoría funciona al agregar 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. Entonces, el usuario ve los últimos elementos en lugar de los primeros elementos (en caso de tener muchos elementos para mostrar), después de tocar la rueda giratoria por primera vez.

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

private void loadSpinner(){ HintArrayAdapter hintAdapter = new HintArrayAdapter<String>(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<T> extends ArrayAdapter<T> { 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; } }

establezca el siguiente diseño en @Override getDropDownView () cuando la posición es 0, para ocultar la primera fila de pistas.

R.layout.spinner_hint_list_item_layout:

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content" > </LinearLayout>


Manejo esto usando un botón en lugar de un Spinner. Tengo el proyecto de muestra en GitHub.

En el proyecto, estoy mostrando tanto el Spinner como el botón para mostrar que realmente se ven idénticos. Excepto el botón, puede establecer el texto inicial en lo que desee.

Así es como se ve la actividad:

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<String> adapter = new ArrayAdapter<String>(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(); }}); } }

NOTA: Sí, me doy cuenta de que esto depende del tema aplicado y el aspecto será ligeramente diferente si se usa Theme.Holo. Sin embargo, si estás usando uno de los temas heredados como Theme.Black, estás listo.


Ninguna de las respuestas enviadas anteriormente realmente funcionó de la manera que quería resolver este problema. Para mí, la solución ideal sería la de "Seleccionar uno" (o el texto inicial) cuando se muestre por primera vez la rueda giratoria. Cuando el usuario toca la rueda giratoria, el texto inicial no debe formar parte del menú desplegable que se muestra.

Para complicar aún más mi situación particular, los datos de mi spinner vienen desde un cursor que se carga a través de las devoluciones de llamada del LoaderManager.

Después de una experimentación considerable se me ocurrió la siguiente solución:

public class MyFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor>{ 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); } } }


Para mí funcionó algo como esto. tiene la mejora que solo cambia el texto en ALGUNAS opciones, no en todas.

Primero tomo los nombres de la ruleta y creo el arrayadapter con una vista personalizada, pero no importa ahora, la clave es anular el getView, y dentro cambiar los valores que necesita cambiar. En mi caso solo fue el primero, el resto lo dejo el original.

public void rellenarSpinnerCompeticiones(){ spinnerArrayCompeticiones = new ArrayList<String>(); for(Competicion c: ((Controlador)getApplication()).getCompeticiones()){ spinnerArrayCompeticiones.add(c.getNombre()); } //ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<String>(this,R.layout.spinner_item_competicion,spinnerArrayCompeticiones); ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<String>(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); }


Parece una solución banal, pero por lo general pongo simplemente un TextView en la parte frontal de la ruleta. Todo el XML se ve así. (hey chicos, no me disparen, sé que a algunos de ustedes no les gusta este tipo de matrimonio):

<FrameLayout android:id="@+id/selectTypesLinear" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" > <Spinner android:id="@+id/spinnerExercises" android:layout_width="match_parent" android:layout_height="match_parent" android:entries="@array/exercise_spinner_entries" android:prompt="@string/exercise_spinner_prompt" /> <TextView android:id="@+id/spinnerSelectText" android:layout_width="match_parent" android:layout_height="match_parent" android:text="Hey! Select this guy!" android:gravity="center" android:background="#FF000000" /> </FrameLayout>

Luego oculto el TextView cuando se seleccionó un artículo. Obviamente, el color de fondo de TextView debe ser el mismo que el de Spinner. Funciona en Android 4.0. No sé en versiones anteriores.

Sí. Debido a que Spinner llama setOnItemSelectedListener al principio, la ocultación de la vista de texto puede ser un poco difícil, pero puede hacerse de esta manera:

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) { } });


También resolví este problema usando el siguiente código. Supongamos que tiene una lista de elementos, por ejemplo,

ArrayList<Item> itemsArrayList = new ArrayList<Item>(); 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);

Ahora tenemos que proporcionar las cadenas al hilandero porque el hilandero no puede entender el objeto. Así que crearemos una nueva lista de matrices con elementos de cadena como este ->

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

Ahora tenemos itemStringArrayListlista de matriz con dos elementos de cadena. Y tenemos que mostrar el texto "Seleccionar elemento" como primer elemento. Así que tenemos que insertar una nueva cadena en el itemStringArrayList.

itemStringArrayList.add("Select Item");

Ahora tenemos una lista de matrices itemsArrayListy queremos mostrar dos elementos en el menú desplegable. Pero la condición aquí es ... Si no seleccionamos nada, Select Itemdebería aparecer como primer elemento que no se habilitará.

Entonces podemos implementar esta funcionalidad como esta. Si necesita cargar los elementos de la lista de matrices en el dispositivo de giro de Android. Así que tendrás que usar algún adaptador. Así que aquí voy a usar el ArrayAdapter. Podemos usar el adaptador personalizado también.

ArrayAdapter<String> itemsArrayAdapter = new ArrayAdapter<String>(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);

Aquí en este código. Estamos utilizando el diseño de giro personalizado, es decir R.layout.spinner_item. Es una simple vista de texto.

<?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="10dp" android:textStyle="italic" android:fontFamily="sans-serif-medium" />

Necesitamos deshabilitar el primer texto en la ruleta. Así que para la posición 0 estamos deshabilitando el texto. Y también se puede establecer el color al anular el método getDropDownView. Así que de esta manera obtendremos el spinner esperado.


si se enfrenta a este problema cuando sus elementos se completan desde la base de datos-cursor ,

La solución más simple que encontré en this respuesta SO:

use UNION en su consulta de adaptador de cursor y agregue el elemento adicional con id = -1 al resultado de la consulta, sin agregarlo realmente al DB:

algo como:

db.rawQuery ("SELECT iWorkerId como _id, nvLastName como nombre FROM Worker w UNION SELECT -1 como _id, '''' como nombre", nulo);

Si el elemento seleccionado es -1, entonces es el valor predeterminado. De lo contrario es un registro de la tabla.