¿Cómo establecer el elemento seleccionado de Spinner por valor, no por posición?


297

Tengo una vista de actualización, donde necesito preseleccionar el valor almacenado en la base de datos para un Spinner.

Tenía en mente algo como esto, pero Adapterno tiene ningún indexOfmétodo, así que estoy atascado.

void setSpinner(String value)
{
    int pos = getSpinnerField().getAdapter().indexOf(value);
    getSpinnerField().setSelection(pos);
}

Respuestas:


646

Supongamos que Spinnerse nombra mSpinnery contiene una de sus opciones: "algún valor".

Para encontrar y comparar la posición de "algún valor" en el Spinner, use esto:

String compareValue = "some value";
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this, R.array.select_state, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mSpinner.setAdapter(adapter);
if (compareValue != null) {
    int spinnerPosition = adapter.getPosition(compareValue);
    mSpinner.setSelection(spinnerPosition);
}

55
con un adaptador personalizado, tendrá que escribir (anular) el código de getPosition ()
Soham

3
¿Qué tal si no está comprobando una cadena sino un elemento dentro de un objeto y no es posible usar solo toString () porque el valor de la ruleta varía de la salida de toString ().
Ajibola

1
Sé que esto es muy antiguo, pero ahora lanza una llamada sin control para obtener la Posición (T)
Brad Bass

tuvieron errores similares, pero el uso de esta manera de la vieja escuela ayudó: stackoverflow.com/questions/25632549/…
Manny265

Hmm ... Ahora, ¿qué sucede si extraigo el valor de, por ejemplo, Parse.com, y quiero consultar al usuario para que la selección de ruleta predeterminada esté predeterminada en el valor de la base de datos del usuario?
drearypanoramic

141

Una forma sencilla de configurar la ruleta en función del valor es

mySpinner.setSelection(getIndex(mySpinner, myValue));

 //private method of your class
 private int getIndex(Spinner spinner, String myString){
     for (int i=0;i<spinner.getCount();i++){
         if (spinner.getItemAtPosition(i).toString().equalsIgnoreCase(myString)){
             return i;
         }
     }

     return 0;
 } 

El camino hacia el código complejo ya está allí, esto es mucho más claro.


77
Olvidó agregar break;cuando se encuentra el índice para acelerar el proceso.
Spacebiker

¿por qué no usar do {} while () para evitar usar break?
Catluc

@ Catluc, hay muchas maneras de llegar a la solución, tú eliges ... lo que mejor te funcione
Akhil Jain

44
En lugar de 0eso, debe regresar -1si no se encuentra el valor, como se muestra en mi respuesta: stackoverflow.com/a/32377917/1617737 :-)
ban-geoengineering

2
@ prohibición de geoingeniería que escribí 0como escenario de respaldo. Si configura -1, qué elemento sería visible en la ruleta, supongo que el elemento 0 del adaptador de la ruleta, agregando -1 también agrega sobrepeso al verificar si el valor es -1 o no, porque la configuración -1 causará una excepción.
Akhil Jain

34

Mantengo una ArrayList separada de todos los elementos en mis Spinners. De esta manera puedo hacer indexOf en ArrayList y luego usar ese valor para establecer la selección en el Spinner.


No hay otra manera, ¿sabes?
Pentium10

1
¿Cómo configurar la selección a nada? (si el elemento no está en la lista)
Pentium10

55
HashMap.get daría una mejor velocidad de búsqueda que ArrayList.indexOf
Dandre Allison el

29

Basado en la respuesta de Merrill , se me ocurrió esta solución de línea única ... no es muy bonita, pero puedes culpar a quien mantiene el código Spinnerpor descuidar la inclusión de una función que hace esto por eso.

mySpinner.setSelection(((ArrayAdapter<String>)mySpinner.getAdapter()).getPosition(myString));

Recibirás una advertencia sobre cómo ArrayAdapter<String>se desmarca el lanzamiento de a ... en realidad, puedes usar un ArrayAdaptercomo Merrill, pero eso solo cambia una advertencia por otra.


Para deshacerse de la advertencia no verificada, debe usar <? > en tu reparto en lugar de <String>. De hecho, cada vez que lanzas algo con un tipo, deberías estar usando <? >.
xbakesx

No, si lanzo a un <? > me da un error en lugar de una advertencia: "El método getPosition (?) en el tipo ArrayAdapter <?> no es aplicable para el argumento (String)".
ArtOfWarfare

Correcto, entonces pensará que es un ArrayAdapter sin tipo, por lo que no asumirá que es un ArrayAdapter <String>. Entonces, para evitar la advertencia, deberá enviarla a ArrayAdapter <? > luego transmita el resultado de su adapter.get () a una Cadena.
xbakesx

@Dadani: supongo que nunca has usado Python antes, porque esto es estúpidamente complicado.
ArtOfWarfare

De acuerdo, no he jugado con Python @ArtOfWarfare, pero esta es una forma rápida para ciertas tareas.
Daniel Dut

13

Si está utilizando una matriz de cadenas, esta es la mejor manera:

int selectionPosition= adapter.getPosition("YOUR_VALUE");
spinner.setSelection(selectionPosition);

10

Puedes usar esto también,

String[] baths = getResources().getStringArray(R.array.array_baths);
mSpnBaths.setSelection(Arrays.asList(baths).indexOf(value_here));

Trabajo brillante!
Sadman Hasan

8

Si necesita tener un método indexOf en cualquier adaptador antiguo (y no conoce la implementación subyacente), puede usar esto:

private int indexOf(final Adapter adapter, Object value)
{
    for (int index = 0, count = adapter.getCount(); index < count; ++index)
    {
        if (adapter.getItem(index).equals(value))
        {
            return index;
        }
    }
    return -1;
}

7

Basado en la respuesta de Merrill aquí está cómo hacer con un CursorAdapter

CursorAdapter myAdapter = (CursorAdapter) spinner_listino.getAdapter(); //cast
    for(int i = 0; i < myAdapter.getCount(); i++)
    {
        if (myAdapter.getItemId(i) == ordine.getListino() )
        {
            this.spinner_listino.setSelection(i);
            break;
        }
    }

6

Use la siguiente línea para seleccionar usando el valor:

mSpinner.setSelection(yourList.indexOf("value"));

3

Estoy usando un adaptador personalizado, para eso este código es suficiente:

yourSpinner.setSelection(arrayAdapter.getPosition("Your Desired Text"));

Entonces, su fragmento de código será así:

void setSpinner(String value)
    {
         yourSpinner.setSelection(arrayAdapter.getPosition(value));
    }

3

Este es mi método simple para obtener el índice por cadena.

private int getIndexByString(Spinner spinner, String string) {
    int index = 0;

    for (int i = 0; i < spinner.getCount(); i++) {
        if (spinner.getItemAtPosition(i).toString().equalsIgnoreCase(string)) {
            index = i;
            break;
        }
    }
    return index;
}

3

Puede usarlo de esta manera, simplemente haga su código más simple y más claro.

ArrayAdapter<String> adapter = (ArrayAdapter<String>) spinnerCountry.getAdapter();
int position = adapter.getPosition(obj.getCountry());
spinnerCountry.setSelection(position);

Espero eso ayude.


2

aqui esta mi solucion

List<Country> list = CountryBO.GetCountries(0);
CountriesAdapter dataAdapter = new CountriesAdapter(this,list);
dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spnCountries.setAdapter(dataAdapter);
spnCountries.setSelection(dataAdapter.getItemIndexById(userProfile.GetCountryId()));

y getItemIndexById a continuación

public int getItemIndexById(String id) {
    for (Country item : this.items) {
        if(item.GetId().toString().equals(id.toString())){
            return this.items.indexOf(item);
        }
    }
    return 0;
}

¡Espero que esto ayude!


2

Aquí se explica cómo hacerlo si está utilizando un SimpleCursorAdapter(donde columnNameestá el nombre de la columna de base de datos que utilizó para completar su spinner):

private int getIndex(Spinner spinner, String columnName, String searchString) {

    //Log.d(LOG_TAG, "getIndex(" + searchString + ")");

    if (searchString == null || spinner.getCount() == 0) {

        return -1; // Not found
    }
    else {

        Cursor cursor = (Cursor)spinner.getItemAtPosition(0);

        int initialCursorPos = cursor.getPosition(); //  Remember for later

        int index = -1; // Not found
        for (int i = 0; i < spinner.getCount(); i++) {

            cursor.moveToPosition(i);
            String itemText = cursor.getString(cursor.getColumnIndex(columnName));

            if (itemText.equals(searchString)) {
                index = i; // Found!
                break;
            }
        }

        cursor.moveToPosition(initialCursorPos); // Leave cursor as we found it.

        return index;
    }
}

Además (un refinamiento de la respuesta de Akhil ), esta es la forma correspondiente de hacerlo si está llenando su Spinner desde una matriz:

private int getIndex(Spinner spinner, String searchString) {

    if (searchString == null || spinner.getCount() == 0) {

        return -1; // Not found

    }
    else {

        for (int i = 0; i < spinner.getCount(); i++) {
            if (spinner.getItemAtPosition(i).toString().equals(searchString)) {
                return i; // Found!
            }
        }

        return -1; // Not found
    }
};

1

Si establece una matriz XML en la ruleta en el diseño XML, puede hacer esto

final Spinner hr = v.findViewById(R.id.chr);
final String[] hrs = getResources().getStringArray(R.array.hours);
if(myvalue!=null){
   for (int x = 0;x< hrs.length;x++){
      if(myvalue.equals(hrs[x])){
         hr.setSelection(x);
      }
   }
}

0

En realidad, hay una manera de obtener esto usando una búsqueda de índice en el Adaptador de matriz y todo esto se puede hacer con reflexión. Incluso fui un paso más allá, ya que tenía 10 Spinners y quería establecerlos dinámicamente desde mi base de datos y la base de datos contiene el valor solo no el texto, ya que el Spinner realmente cambia semana a semana, por lo que el valor es mi número de identificación de la base de datos.

 // Get the JSON object from db that was saved, 10 spinner values already selected by user
 JSONObject json = new JSONObject(string);
 JSONArray jsonArray = json.getJSONArray("answer");

 // get the current class that Spinner is called in 
 Class<? extends MyActivity> cls = this.getClass();

 // loop through all 10 spinners and set the values with reflection             
 for (int j=1; j< 11; j++) {
      JSONObject obj = jsonArray.getJSONObject(j-1);
      String movieid = obj.getString("id");

      // spinners variable names are s1,s2,s3...
      Field field = cls.getDeclaredField("s"+ j);

      // find the actual position of value in the list     
      int datapos = indexedExactSearch(Arrays.asList(Arrays.asList(this.data).toArray()), "value", movieid) ;
      // find the position in the array adapter
      int pos = this.adapter.getPosition(this.data[datapos]);

      // the position in the array adapter
      ((Spinner)field.get(this)).setSelection(pos);

}

Aquí está la búsqueda indexada que puede usar en casi cualquier lista siempre que los campos estén en el nivel superior del objeto.

    /**
 * Searches for exact match of the specified class field (key) value within the specified list.
 * This uses a sequential search through each object in the list until a match is found or end
 * of the list reached.  It may be necessary to convert a list of specific objects into generics,
 * ie: LinkedList&ltDevice&gt needs to be passed as a List&ltObject&gt or Object[&nbsp] by using 
 * Arrays.asList(device.toArray(&nbsp)).
 * 
 * @param list - list of objects to search through
 * @param key - the class field containing the value
 * @param value - the value to search for
 * @return index of the list object with an exact match (-1 if not found)
 */
public static <T> int indexedExactSearch(List<Object> list, String key, String value) {
    int low = 0;
    int high = list.size()-1;
    int index = low;
    String val = "";

    while (index <= high) {
        try {
            //Field[] c = list.get(index).getClass().getDeclaredFields();
            val = cast(list.get(index).getClass().getDeclaredField(key).get(list.get(index)) , "NONE");
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

        if (val.equalsIgnoreCase(value))
            return index; // key found

        index = index + 1;
    }

    return -(low + 1);  // key not found return -1
}

El método de conversión que se puede crear para todas las primitivas aquí es uno para string e int.

        /**
 *  Base String cast, return the value or default
 * @param object - generic Object
 * @param defaultValue - default value to give if Object is null
 * @return - returns type String
 */
public static String cast(Object object, String defaultValue) {
    return (object!=null) ? object.toString() : defaultValue;
}


    /**
 *  Base integer cast, return the value or default
 * @param object - generic Object
 * @param defaultValue - default value to give if Object is null
 * @return - returns type integer
 */
public static int cast(Object object, int defaultValue) { 
    return castImpl(object, defaultValue).intValue();
}

    /**
 *  Base cast, return either the value or the default
 * @param object - generic Object
 * @param defaultValue - default value to give if Object is null
 * @return - returns type Object
 */
public static Object castImpl(Object object, Object defaultValue) {
    return object!=null ? object : defaultValue;
}

0

Para hacer que la aplicación recuerde los últimos valores de flecha seleccionados, puede usar el siguiente código:

  1. El siguiente código lee el valor de la ruleta y establece la posición de la ruleta en consecuencia.

    public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    
    int spinnerPosition;
    
    Spinner spinner1 = (Spinner) findViewById(R.id.spinner1);
    ArrayAdapter<CharSequence> adapter1 = ArrayAdapter.createFromResource(
            this, R.array.ccy_array,
            android.R.layout.simple_spinner_dropdown_item);
    adapter1.setDropDownViewResource(android.R.layout.simple_list_item_activated_1);
    // Apply the adapter to the spinner
    spinner1.setAdapter(adapter1);
    // changes to remember last spinner position
    spinnerPosition = 0;
    String strpos1 = prfs.getString("SPINNER1_VALUE", "");
    if (strpos1 != null || !strpos1.equals(null) || !strpos1.equals("")) {
        strpos1 = prfs.getString("SPINNER1_VALUE", "");
        spinnerPosition = adapter1.getPosition(strpos1);
        spinner1.setSelection(spinnerPosition);
        spinnerPosition = 0;
    }
  2. Y ponga el siguiente código donde sepa que están presentes los últimos valores de la ruleta, o en otro lugar, según sea necesario. Este código básicamente escribe el valor de la ruleta en SharedPreferences.

        Spinner spinner1 = (Spinner) findViewById(R.id.spinner1);
        String spinlong1 = spinner1.getSelectedItem().toString();
        SharedPreferences prfs = getSharedPreferences("WHATEVER",
                Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = prfs.edit();
        editor.putString("SPINNER1_VALUE", spinlong1);
        editor.commit();

0

Tuve el mismo problema al intentar seleccionar el elemento correcto en una rueda giratoria poblada con un cursorLoader. Recuperé la identificación del elemento que quería seleccionar primero de la tabla 1 y luego utilicé un CursorLoader para llenar la ruleta. En onLoadFinished hice un ciclo a través del cursor que llena el adaptador de la ruleta hasta que encontré el elemento que coincidía con la identificación que ya tenía. Luego asignó el número de fila del cursor a la posición seleccionada de la ruleta. Sería bueno tener una función similar para pasar la identificación del valor que desea seleccionar en la ruleta al completar los detalles en un formulario que contiene los resultados guardados de la ruleta.

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {  
  adapter.swapCursor(cursor);

  cursor.moveToFirst();

 int row_count = 0;

 int spinner_row = 0;

  while (spinner_row < 0 || row_count < cursor.getCount()){ // loop until end of cursor or the 
                                                             // ID is found 

    int cursorItemID = bCursor.getInt(cursor.getColumnIndexOrThrow(someTable.COLUMN_ID));

    if (knownID==cursorItemID){
    spinner_row  = row_count;  //set the spinner row value to the same value as the cursor row 

    }
cursor.moveToNext();

row_count++;

  }

}

spinner.setSelection(spinner_row ); //set the selected item in the spinner

}

0

Como algunas de las respuestas anteriores son muy correctas, solo quiero asegurarme de que ninguno de ustedes caiga en este problema.

Si establece los valores en el ArrayListuso String.format, DEBE obtener la posición del valor utilizando la misma estructura de cadena String.format.

Un ejemplo:

ArrayList<String> myList = new ArrayList<>();
myList.add(String.format(Locale.getDefault() ,"%d", 30));
myList.add(String.format(Locale.getDefault(), "%d", 50));
myList.add(String.format(Locale.getDefault(), "%d", 70));
myList.add(String.format(Locale.getDefault(), "%d", 100));

Debe obtener la posición del valor necesario de esta manera:

myList.setSelection(myAdapter.getPosition(String.format(Locale.getDefault(), "%d", 70)));

De lo contrario, obtendrás el -1artículo no encontrado.

Solía Locale.getDefault()por el idioma árabe .

Espero que te sea útil.


0

Aquí está mi solución con suerte completa. Tengo la siguiente enumeración:

public enum HTTPMethod {GET, HEAD}

utilizado en la siguiente clase

public class WebAddressRecord {
...
public HTTPMethod AccessMethod = HTTPMethod.HEAD;
...

Código para establecer el spinner por HTTPMethod enum-member:

    Spinner mySpinner = (Spinner) findViewById(R.id.spinnerHttpmethod);
    ArrayAdapter<HTTPMethod> adapter = new ArrayAdapter<HTTPMethod>(this, android.R.layout.simple_spinner_item, HTTPMethod.values());
    mySpinner.setAdapter(adapter);
    int selectionPosition= adapter.getPosition(webAddressRecord.AccessMethod);
    mySpinner.setSelection(selectionPosition);

Donde R.id.spinnerHttpmethodse define en un archivo de diseño, y android.R.layout.simple_spinner_itemes entregado por android-studio.


0
YourAdapter yourAdapter =
            new YourAdapter (getActivity(),
                    R.layout.list_view_item,arrData);

    yourAdapter .setDropDownViewResource(R.layout.list_view_item);
    mySpinner.setAdapter(yourAdapter );


    String strCompare = "Indonesia";

    for (int i = 0; i < arrData.length ; i++){
        if(arrData[i].getCode().equalsIgnoreCase(strCompare)){
                int spinnerPosition = yourAdapter.getPosition(arrData[i]);
                mySpinner.setSelection(spinnerPosition);
        }
    }

Bienvenido a StackOverflow. Las respuestas con solo código en ellas tienden a marcarse para su eliminación ya que son de "baja calidad". Lea la sección de ayuda para responder preguntas y luego considere agregar algunos comentarios a su respuesta.
Graham

@ user2063903, agregue una explicación en su respuesta.
LuFFy

0

muy simple solo use getSelectedItem();

p.ej :

ArrayAdapter<CharSequence> type=ArrayAdapter.createFromResource(this,R.array.admin_typee,android.R.layout.simple_spinner_dropdown_item);
        type.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        mainType.setAdapter(type);

String group=mainType.getSelectedItem().toString();

el método anterior devuelve un valor de cadena

en el anterior el R.array.admin_typees un archivo de recursos de cadena en valores

solo cree un archivo .xml en valores >> cadenas


0

Suponga que necesita llenar la ruleta desde el conjunto de cadenas desde el recurso, y desea mantener seleccionado el valor del servidor. Por lo tanto, esta es una forma de establecer un valor seleccionado del servidor en la ruleta.

pincodeSpinner.setSelection(resources.getStringArray(R.array.pincodes).indexOf(javaObject.pincode))

¡Espero eso ayude! PD: el código está en Kotlin!


0

Como necesitaba algo, que también funciona con la localización , se me ocurrieron estos dos métodos:

    private int getArrayPositionForValue(final int arrayResId, final String value) {
        final Resources english = Utils.getLocalizedResources(this, new Locale("en"));
        final List<String> arrayValues = Arrays.asList(english.getStringArray(arrayResId));

        for (int position = 0; position < arrayValues.size(); position++) {
            if (arrayValues.get(position).equalsIgnoreCase(value)) {
                return position;
            }
        }
        Log.w(TAG, "getArrayPosition() --> return 0 (fallback); No index found for value = " + value);
        return 0;
    }

Como puede ver, también me topé con la complejidad adicional de la distinción entre mayúsculas y minúsculas entre arrays.xml y la valueque estoy comparando. Si no tiene esto, el método anterior se puede simplificar a algo como:

return arrayValues.indexOf(value);

Método auxiliar estático

public static Resources getLocalizedResources(Context context, Locale desiredLocale) {
        Configuration conf = context.getResources().getConfiguration();
        conf = new Configuration(conf);
        conf.setLocale(desiredLocale);
        Context localizedContext = context.createConfigurationContext(conf);
        return localizedContext.getResources();
    }

-3

debe pasar su adaptador personalizado con una posición como REPEAT [posición]. y funciona correctamente

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.