Come impostare l'elemento selezionato di Spinner per valore, non per posizione?


297

Ho una vista di aggiornamento, in cui devo preselezionare il valore memorizzato nel database per uno Spinner.

Avevo in mente qualcosa del genere, ma Adapternon ha un indexOfmetodo, quindi sono bloccato.

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

Risposte:


646

Supponiamo che il tuo Spinnernome sia mSpinnere contenga come una delle sue scelte: "un certo valore".

Per trovare e confrontare la posizione di "un valore" nello Spinner, usa questo:

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

5
con un adattatore personalizzato dovrai scrivere (sovrascrivere) il codice per getPosition ()
Soham il

3
Che ne dici se non stai controllando una stringa ma un elemento all'interno di un oggetto e non è possibile usare semplicemente toString () perché il valore dello spinner varia dall'output di toString ().
Ajibola,

1
So che è molto vecchio, ma ora genera una chiamata non selezionata per ottenerePosition (T)
Brad Bass

avevano gettato errori simili, ma utilizzando in questo modo vecchia scuola aiutato: stackoverflow.com/questions/25632549/...
Manny265

Hmm ... Ora se sto estraendo il valore da, per esempio, Parse.com, e voglio interrogare l'utente in modo che la selezione di spinner predefinita sia impostata sul valore del database dell'utente?
Drearypanoramic il

141

Un modo semplice per impostare il filatore in base al valore è

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

Il modo per codice complesso è già lì, questo è solo molto più semplice.


7
Hai dimenticato di aggiungere break;quando viene trovato l'indice per accelerare il processo.
Spacebiker,

perché non usare do {} while () per evitare di usare break?
Catluc,

@Catluc ci sono n modi per arrivare alla soluzione, tu scegli ... cosa funziona meglio per te
Akhil Jain,

4
Piuttosto che 0, dovresti restituire -1se il valore non viene trovato - come mostrato nella mia risposta: stackoverflow.com/a/32377917/1617737 :-)
ban-geoengineering

2
@ ban-geoengineering Ho scritto 0come scenario di backup. Se si imposta -1, quale elemento sarebbe visibile sullo spinner, suppongo che il nono elemento dell'adattatore dello spinner, l'aggiunta di -1 aggiunga anche un sovrappeso nel controllare se il valore è -1 o meno, poiché l'impostazione -1 causerà un'eccezione.
Akhil Jain,

34

Tengo un ArrayList separato di tutti gli elementi nei miei Spinner. In questo modo posso eseguire indexOf su ArrayList e quindi utilizzare quel valore per impostare la selezione nello Spinner.


Non c'è altro modo, sai?
Pentium10

1
Come impostare la selezione su nulla? (se l'articolo non è nell'elenco)
Pentium10

5
HashMap.get darebbe una velocità di ricerca migliore di ArrayList.indexOf
Dandre Allison

29

Sulla base della risposta di Merrill , mi è venuta in mente questa soluzione a linea singola ... non è molto carina, ma puoi incolpare chiunque mantenga il codice per Spinneraver trascurato di includere una funzione che lo fa per quello.

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

Riceverai un avviso su come il cast di un ArrayAdapter<String>non è selezionato ... davvero, potresti semplicemente usare un ArrayAdaptercome ha fatto Merrill, ma questo scambia solo un avviso con un altro.


Per eliminare l'avvertimento non selezionato è necessario utilizzare <? > nel tuo cast anziché <String>. Infatti ogni volta che lanci qualcosa con un tipo, dovresti usare <? >.
xbakesx,

No, se eseguo il cast su un <? > mi dà un errore invece di un avvertimento: "Il metodo getPosition (?) nel tipo ArrayAdapter <?> non è applicabile per l'argomento (String)."
ArtOfWarfare il

Corretto, penserà quindi che sia un ArrayAdapter senza tipo, quindi non supporrà che sia un ArrayAdapter <String>. Quindi per evitare l'avvertimento dovrai lanciarlo su ArrayAdapter <? > quindi cast il risultato di adapter.get () su una stringa.
xbakesx,

@Dadani - Suppongo che non hai mai usato Python prima, perché questo è stupidamente contorto.
ArtOfWarfare,

D'accordo, non ho giocato con Python @ArtOfWarfare, ma questo è un modo rapido per alcune attività.
Daniel Dut,

13

se stai usando un array di stringhe questo è il modo migliore:

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

10

Puoi usare anche questo,

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

Lavoro brillante!
Sadman Hasan,

8

Se è necessario disporre di un metodo indexOf su qualsiasi vecchio adattatore (e non si conosce l'implementazione sottostante), è possibile utilizzare questo:

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

Sulla base della risposta di Merrill, ecco come fare 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

Utilizzare la seguente riga per selezionare usando il valore:

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

3

Sto usando un adattatore personalizzato, per questo questo codice è sufficiente:

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

Quindi, lo snippet di codice sarà così:

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

3

Questo è il mio metodo semplice per ottenere l'indice per stringa.

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

Puoi usarlo in questo modo, rendi il tuo codice più semplice e più chiaro.

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

Spero che sia d'aiuto.


2

ecco la mia soluzione

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

e getItemIndexById di seguito

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

Spero che questo aiuto!


2

Ecco come farlo se stai usando un SimpleCursorAdapter(dov'è columnNameil nome della colonna db che hai usato per popolare il tuo 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;
    }
}

Inoltre (un perfezionamento della risposta di Akhil ) questo è il modo corrispondente per farlo se stai riempiendo il tuo Spinner da un array:

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

Se si imposta un array XML sullo spinner nel layout XML, è possibile farlo

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

Esiste effettivamente un modo per ottenerlo utilizzando una ricerca dell'indice su AdapterArray e tutto ciò può essere fatto con la riflessione. Ho anche fatto un ulteriore passo avanti perché avevo 10 Spinner e volevo impostarli dinamicamente dal mio database e il database contiene il valore non solo il testo poiché lo Spinner cambia in realtà da una settimana all'altra, quindi il valore è il mio numero ID dal database.

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

}

Ecco la ricerca indicizzata che puoi utilizzare in quasi tutti gli elenchi, purché i campi siano al primo livello dell'oggetto.

    /**
 * 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
}

Il metodo cast che può essere creato per tutte le primitive qui è uno per 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

Per fare in modo che l'applicazione ricordi gli ultimi valori di selezione selezionati, è possibile utilizzare il codice seguente:

  1. Il codice seguente legge il valore del filatore e imposta la posizione del filatore di conseguenza.

    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. E metti sotto il codice dove conosci gli ultimi valori di spinner o da qualche altra parte come richiesto. Questo pezzo di codice scrive sostanzialmente il valore del filatore in 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

Ho avuto lo stesso problema quando provavo a selezionare l'elemento corretto in uno spinner popolato usando cursoreLoader. Ho recuperato l'id dell'elemento che volevo selezionare prima dalla tabella 1 e poi ho usato un CursorLoader per popolare lo spinner. In onLoadFinished ho pedalato attraverso il cursore popolando l'adattatore del filatore fino a quando ho trovato l'oggetto che corrispondeva all'ID che avevo già. Quindi assegnato il numero di riga del cursore alla posizione selezionata dello spinner. Sarebbe bello avere una funzione simile per passare l'id del valore che si desidera selezionare nello spinner quando si popolano i dettagli su un modulo contenente i risultati salvati dello spinner.

@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

Poiché alcune delle risposte precedenti sono molto giuste, voglio solo assicurarmi che nessuno di voi cada in questo problema.

Se si impostano i valori su ArrayListusing String.format, è NECESSARIO ottenere la posizione del valore utilizzando la stessa struttura di stringhe String.format.

Un esempio:

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

È necessario ottenere la posizione del valore necessario in questo modo:

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

Altrimenti, otterrai l' -1oggetto non trovato!

Ho usato a Locale.getDefault()causa della lingua araba .

Spero che ti sarà utile.


0

Ecco la mia soluzione, si spera completa. Ho il seguente enum:

public enum HTTPMethod {GET, HEAD}

usato nella seguente classe

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

Codice per impostare lo spinner tramite 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);

Dove R.id.spinnerHttpmethodè definito in un file di layout ed android.R.layout.simple_spinner_itemè fornito da 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);
        }
    }

Benvenuto in StackOverflow. Le risposte con solo codice in esse tendono ad essere contrassegnate per la cancellazione in quanto sono "di bassa qualità". Si prega di leggere la sezione di aiuto per rispondere alle domande, quindi prendere in considerazione l'aggiunta di alcuni commenti alla risposta.
Graham,

@ user2063903, aggiungere una spiegazione nella risposta.
LuFFy,

0

molto semplice basta usare getSelectedItem();

per esempio :

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

il metodo sopra restituisce un valore stringa

in quanto sopra R.array.admin_typeè un file di risorse stringa in valori

basta creare un file .xml in valori >> stringhe


0

Supponiamo di dover riempire il filatore dall'array di stringhe dalla risorsa e di voler mantenere selezionato il valore dal server. Quindi, questo è un modo per impostare un valore selezionato dal server nello spinner.

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

Spero che sia d'aiuto! PS il codice è in Kotlin!


0

Dato che avevo bisogno di qualcosa, che funziona anche con la localizzazione , ho trovato questi due metodi:

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

Come puoi vedere, mi sono anche imbattuto in un'ulteriore complessità della distinzione tra maiuscole e minuscole tra arrays.xml e il valueconfronto con cui sto confrontando. Se non lo hai, il metodo sopra può essere semplificato a qualcosa del tipo:

return arrayValues.indexOf(value);

Metodo di supporto statico

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

devi passare il tuo adattatore personalizzato con posizione come REPEAT [posizione]. e funziona correttamente.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.