¿Cómo hacer un Android Spinner con el texto inicial "Seleccione uno"?

569

Quiero usar 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 ruleta, 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 control giratorio 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 "Seleccionar uno" a los elementos, 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?

Pieter Kuijpers
fuente
66
La solución perfecta reside en esta pregunta: stackoverflow.com/questions/9863378/… Simplemente anule el método getDropDownView ().
Sourab Sharma
¿Has intentado configurar el primer elemento de tu adaptador en "Seleccionar uno"?
IgorGanapolsky
[¡Aquí hay otra gran solución!] [1] [1]: stackoverflow.com/questions/9863378/…
AirtonCarneiro
spinner reutilizable: github.com/henrychuangtw/ReuseSpinner
HenryChuang

Respuestas:

255

Aquí hay una solución general que anula la Spinnervista. Se anula setAdapter()para establecer la posición inicial en -1, y representa el suministrado SpinnerAdapterpara mostrar la cadena de solicitud para la posición inferior a 0.

Esto se ha 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 al privado AdapterView.setNextSelectedPositionInt()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 toleraría algo como esto, pero esta pregunta se ha hecho 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);
        }
    }
}
emmby
fuente
77
@emmby ¿Tiene alguna idea de cómo borrar la selección después de que el usuario la configuró? Intenté refactorizar las dos llamadas invoke () en un método clearSelection (), pero realmente no funciona. Aunque la lista emergente muestra el elemento seleccionado anteriormente como no seleccionado, el widget de flecha todavía lo muestra como seleccionado, y si el usuario selecciona el mismo elemento nuevamente, no se llama a onItemSelected ().
Qwertie
3
¿podrían algunos explicar cómo usar la clase anterior?
Bishan
44
Esta solución no es 100% perfecta en Android 4.2 (Cyanogenmod 10.1), usando Android: entradas. La altura de TextView inflado es menor que la altura de cualquier recurso que infla el adaptador predeterminado. Entonces, cuando realmente selecciona una opción, la altura aumenta, ~ 10px en mi Galaxy S, lo cual no es aceptable. He intentado varias cosas (gravedad, relleno, margen, etc.) y ninguna funcionó de manera confiable en todos los dispositivos, por lo que optaré por una solución diferente.
Maragues
3
@DavidDoria Debe usar la clase NoDefaultSpinner en su archivo de diseño. Copie la fuente de arriba en su proyecto, por ejemplo, en el paquete com.example.customviews. Ahora en su diseño xml, en lugar de <Spinner ...> use <com.example.customviews.NoDefaultSpinner ...> El resto del código puede permanecer igual. No olvide agregar el atributo android: prompt a la vista <com.example.customviews.NoDefaultSpinner> en su diseño.
Ridcully
2
@emmby spinnerBrand.setSelection (-1); no funciona
Sachin C
291

Lo que puede hacer es decorarlo SpinnerAdaptercon uno que presente una vista '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 adaptar el código existente y también funciona bien con CursorLoaders. (Intercambiar el cursor en la envoltura, cursorAdapterpor supuesto ...)

Hay un error de Android que hace que sea un poco más difícil reutilizar las vistas. (Por lo tanto, debe usar setTagu otra cosa para asegurarse de que convertViewsea ​​correcto). Spinner no admite múltiples tipos de vista

Notas de código: 2 constructores

Esto le permite utilizar una solicitud 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 cuadro de diálogo. El menú desplegable normalmente no muestra el mensaje)

Define un diseño para 'verse' como un indicador, por ejemplo, atenuado ...

Inicial nada seleccionado

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

Con un aviso estándar

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

Mensaje y nada fila seleccionada

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

}
aaronvargas
fuente
52
Esta es una solución elegante al problema. El código funciona exactamente como copiar y pegar en mi proyecto. +1 para no requerir reflexión.
Richard Le Mesurier
2
Esta es una gran solución. Si alguien quiere saber cómo anular el título, no solo antes de seleccionar un elemento, sino en todo momento, en la llamada a getView (), simplemente devuelva getNothingSelectedView (o cualquier otra vista personalizada) en todo momento. La lista desplegable aún se completará con elementos de su adaptador, pero ahora puede controlar el título DESPUÉS de que algo esté seleccionado también.
OldSchool4664
66
Esta es una solución realmente elegante para un problema que no debería existir (prueba el desarrollo de Iphone). Genial y gracias! Me alegra que alguien haya recordado patrones, etc.
user1700737
3
@prashantwosti, el código se actualizó para funcionar con Lollipop. Específicamente getItemViewType () y getViewTypeCount ().
aaronvargas
3
@aaronvargas, una vez seleccionado un elemento de la ruleta, ¿puedo deshacer y seleccionar "[Seleccionar un planeta]"?
modabeckham
130

Terminé usando un Buttonen su lugar. Si bien a Buttonno es a Spinner, el comportamiento es fácil de personalizar.

Primero cree 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_itemcomo la identificación 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!

HRJ
fuente
10
Estoy de acuerdo con esa respuesta Además, un botón mucho más fácil de peinar que un Spinner.
Romain Piel
@HRJ He implementado la forma en que sugirió, pero el elemento que se seleccionó antes no se resalta (significa que el botón de radio debe estar resaltado con un punto verde en el medio) ... ¿Cómo puedo lograr esto en el método OnClick () de botón. Por favor, ayúdame HRJ .....
Avadhani Y
2
El botón con este diseño es perfecto <Botón android: id = "@ + id / city" android: layout_width = "match_parent" android: layout_height = "wrap_content" android: layout_margin = "5dp" android: gravity = "left" android: background = "@ android: drawable / btn_dropdown" android: text = "@ string / city_prompt" />
kml_ckr
¿Cómo actualizaría el texto del botón para reflejar la selección, como sucedería en una ruleta?
cuña
3
solución del problema: en lugar de SetAdapter use SetSingleChoiceItems
Grzegorz Dev
67

Primero, puede estar interesado en el promptatributo de la Spinnerclase. Vea la imagen a continuación, "Elija un planeta" es el mensaje que se puede configurar en el XML con android:prompt="".

ingrese la descripción de la imagen aquí

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

Puede envolver la rueda giratoria en una vista diferente, interceptar los clics en la vista y luego indicarle CustomSpinnerque cambie el adaptador, pero parece un truco horrible.

¿Realmente necesitas mostrar "Seleccionar uno"?

Casey
fuente
36
No es solo una cuestión de necesidad de mostrar "Seleccionar uno", sino que también trata el caso en el que el valor de la flecha opcional puede dejarse en blanco.
greg7gkb
55
Además, con esta opción, Earth se muestra como la selección en el Spinner antes de que se haya elegido algo, para mi aplicación prefiero que el usuario pueda decir que aún no han elegido nada
dylan murphy
2
esto realmente no responde la pregunta. la gente está buscando una manera de que la rueda giratoria muestre "Seleccione uno" por defecto en lugar del primer elemento de la lista de planetas, en este ejemplo
JMRboosties
58

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

ingrese la descripción de la imagen aquí

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);
Manos
fuente
getItem(getCount())está subrayado rojo para mí? No se puede resolver el método setHint
Zapnologica
Tengo una duda, vi muchas soluciones en este hilo ... pero por qué todo el mundo está agregando una pista a la última. ¿Está mal agregar una pista en la primera fila?
akashPatra
No puedo establecer 'setOnItemSelectedListener (this);' porque estoy usando 'implementa NavigationView.OnNavigationItemSelectedListener', ¿puedo eliminar 'setOnItemSelectedListener (this);' sin problemas?
CGR
@akashpatra La razón por la que agregan una pista para durar es que ArrayAdapter para spinner podría obtener sus valores de diferentes fuentes en tiempo de ejecución.
VinKrish
esto realmente me ayudó
sunil
31

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 "Select One" y luego en onItemSelected, cámbiele el nombre a "One".

No es una solución con clase, pero funciona: D

Marco da Gualdo
fuente
55
Esto no funcionó para mí. Después de elegir el elemento "Uno", sigue diciendo "Seleccionar uno".
Leo Landau
Esto no funcionará porque la interfaz onItemSelected llamará por primera vez siempre.
Vaibhav Kadam
20

No hay una API predeterminada para establecer una sugerencia en Spinner. Para agregarlo, necesitamos una pequeña solución alternativa que no sea una implementación de 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

Yakiv Mospan
fuente
¿Qué es R.id.text1? ¿Es algún diseño o vista? por favor elabore su respuesta
Anand Savjani
Debería serandroid.R.id.text1
Yakiv Mospan
Tengo una duda, vi muchas soluciones en este hilo ... pero por qué todo el mundo está agregando una pista a la última. ¿Está mal agregar una pista en la primera fila?
akashPatra
@akashpatra No recuerdo exactamente, pero parece que hubo un problema cuando traté de hacerlo como la primera lista de elementos. De todos modos, siempre puedes probarlo y comentar aquí, toda la magia aquí está getCount
basada
@YakivMospan Obtengo un NPE cuando lo uso, probablemente debido a Reflection cuando uso ProGuard. ¿Sabes cómo arreglar ésto?
Alan
17

Muchas respuestas aquí, pero me sorprende que nadie sugiriera una solución simple: coloque un TextView en la parte superior del Spinner. Establezca un detector de clics en TextView que oculta TextView muestra el Spinner y llama a spinner.performClick ().

mjancola
fuente
9

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);
    }
}
Rajasekhar
fuente
66
El problema con este enfoque es que todavía selecciona el primer elemento de la lista cuando aparece la lista. Debido a que ya está seleccionado, no puede tocarlo para seleccionarlo; actúa como si no hubiera sucedido ninguna selección.
jwadsack
7

Puede cambiarlo a una vista de texto y usar esto:

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

y luego definir la android:textpropiedad.

Christian Vielma
fuente
Funciona solo para API 14 y superior.
Giulio Piancastelli
6

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 mediante programación)>

featuresAdapter.add("some string");

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

Trgraglia
fuente
Tampoco es necesario notificar aDataSetChanged (), ya que debe establecerse en verdadero de forma predeterminada.
Trgraglia
4

He intentado lo siguiente. Tome un botón y dele el evento de clic. Al cambiar el fondo del botón, parece ser una ruleta.

Declarar como variables globales alertdialog y valor por defecto.

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();
    }
});
Ramesh Akula
fuente
4

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
Cabezas
fuente
esto abre la ruleta en la posición inferior
SpyZip
3

Eche un vistazo a la aplicación iosched para obtener 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 la lista para tratar con el elemento adicional en la parte superior.

Con el adaptador personalizado, puede establecer el texto en "Seleccionar uno" o cualquier otra cosa que desee que diga ese elemento principal.

Deporte
fuente
3

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.

Cirilo
fuente
3

Encontré muchas buenas soluciones para esto. La mayoría funciona agregando 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 la flecha 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 comienzo 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 diseño a continuación 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>
Alireza Sobhani
fuente
3

Además, hay un simple truco para mostrar el valor predeterminado:

Puede agregar un valor predeterminado en su lista y luego agregar toda su colección usando list.addAll(yourCollection);

Ejemplo de código viable aquí:

List<FuelName> fuelList = new ArrayList<FuelName>();
                    fuelList.add(new FuelName(0,"Select One"));
                    fuelList.addAll(response.body());
                    ArrayAdapter adapter = new ArrayAdapter<>(getActivity(), android.R.layout.simple_spinner_item, fuelList);
                    //fuelName.setPrompt("Select Fuel");
                    fuelName.setAdapter(adapter);

Espero que recupere tu complejidad. ¡Feliz codificación!

Majedur Rahaman
fuente
2

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

Tobias
fuente
44
¿Qué hay de ver la lista de artículos? ¿Desea ver la posición "seleccionar uno" en la parte superior? No es solo cuestión de ahorrar.
Krzysztof Wolny
@KrzysztofWolny Spinner muestra de forma predeterminada el elemento en la posición 0
rds
2

Este es mi último ejemplo "todo incluido" 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 strings.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 ningún ítem seleccionable! Gracias a HRJ

salvaje
fuente
1

Al extender SpinnerAdapter, anula dos Viewmétodos de producción, getView(int, View, ViewGroup)y getDropDownView(int, View, ViewGroup). El primero suministra el Viewinsertado en el Spinnermismo; el segundo proporciona el Viewen la lista desplegable (como su nombre indica). Puede anular el comando getView(...)para que, hasta que se seleccione un elemento, muestre TextViewun mensaje que contenga; luego, cuando detecta que un elemento ha sido seleccionado, lo cambia para mostrar un TextViewcorrespondiente a ese.

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

//...
}
Andrew Wyld
fuente
1
He descubierto una falla en este método: el Spinner selecciona automáticamente un elemento de inmediato. Encontraré una forma de solucionar esto en breve.
Andrew Wyld
Hablé muy pronto Sin embargo, no me he rendido. Tenga en cuenta que de acuerdo con el Spinnertutorial (que supuestamente muestra un Toastmensaje DESPUÉS de haber seleccionado un elemento), DEBE funcionar: developer.android.com/resources/tutorials/views/…
Andrew Wyld el
1

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;
    }
  }
}
MPavlak
fuente
1

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

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 a spinner porque spinner no puede entender el objeto. Así que crearemos una nueva lista de matriz con elementos de cadena como este ->

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

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

itemStringArrayList.add("Select Item");

Ahora tenemos una lista de matriz 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 la matriz en el spinner de Android. Entonces tendrá que usar algún adaptador. Así que aquí usaré el ArrayAdapter. También podemos usar el adaptador personalizado.

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 personalizado de spinner, 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. Entonces, para la posición 0, estamos deshabilitando el texto. Y también podemos establecer el color anulando el método getDropDownView. De esta manera obtendremos el spinner esperado.

Shravan Jain
fuente
0

Solo usaría un RadioGroup con RadioButtons si solo tiene tres opciones, puede hacer que todas estén desmarcadas al principio.

stephane k.
fuente
0

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

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

Después de una considerable experimentación, 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);
    }
}
}
Jed
fuente
0

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

En el proyecto, estoy mostrando el Spinner y el botón para mostrar que realmente se ven idénticos. Excepto el botón, puede establecer el texto inicial a 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 usa Theme.Holo. Sin embargo, si está utilizando uno de los temas heredados, como Theme.Black, está listo para comenzar.

SBerg413
fuente
0

si enfrenta este problema cuando sus elementos se rellenan desde el cursor de base de datos ,

La solución más simple que encontré en esta 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 a la base de datos:

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.

dvrm
fuente
0

Parece una solución banal, pero generalmente pongo simplemente un TextView en el frente de la ruleta. Todo el Xml se ve así. (Hola 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 TextView cuando se selecciona un elemento. Obviamente, el color de fondo de TextView debe ser el mismo que el Spinner. Funciona en Android 4.0. No sé en versiones anteriores.

Si. Debido a que Spinner llama a setOnItemSelectedListener al principio, ocultar la vista de texto puede ser un poco complicado, pero se puede hacer 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) {
        }

    });
Claudio Ferraro
fuente
0

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

Primero tomo los nombres de la ruleta y creo el adaptador de matriz con una vista personalizada, pero no importa ahora, la clave es anular getView y cambiar los valores que necesita cambiar. En mi caso fue solo el primero, el resto lo dejo 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);
    }
Rako
fuente
0

aquí hay uno 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);
}
Sayka
fuente
0

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

Agregué mi código para corregir un pequeño error. Eso donde no se recuperaron datos ... ¡Cómo mostrar el texto de solicitud ...!

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

Intente colocar su ruleta en un Relative_layouta y alinee una vista de texto con su ruleta y juegue con la visibilidad de la vista de texto (MOSTRAR / OCULTAR) siempre que el adaptador de la ruleta se cargue o se vacíe.

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

llame a este método después y antes de que el adaptador giratorio 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);
    }

}
Ibrahim AbdelGawad
fuente