Como definir o item selecionado do Spinner por valor, não por posição?


297

Eu tenho uma visualização de atualização, na qual preciso pré-selecionar o valor armazenado no banco de dados para um Spinner.

Eu estava pensando em algo assim, mas o método Adapternão tem indexOf, por isso estou preso.

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

Respostas:


646

Suponha que o seu Spinnerseja nomeado mSpinnere contenha como uma de suas opções: "algum valor".

Para encontrar e comparar a posição de "algum valor" no Spinner, use o seguinte:

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
com um adaptador personalizado que você terá que escrever (override) o código para getPosition ()
Soham

3
Que tal se você não estiver verificando uma string, mas um elemento dentro de um objeto e não for possível usar apenas o toString (), pois o valor do spinner varia da saída de toString ().
precisa

1
Eu sei que isso é muito antiga, mas isso agora lança uma chamada desmarcada para getPosition (T)
Brad Bass

tinha erros semelhantes jogado, mas usando esta maneira da velha escola ajudou: stackoverflow.com/questions/25632549/...
Manny265

Hmm ... Agora, e se eu estiver obtendo o valor, digamos, Parse.com, e quiser consultar o usuário para que a seleção padrão do controle giratório seja padronizada com o valor do banco de dados do usuário?
drearypanoramic

141

Uma maneira simples de definir o girador com base no valor é

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

Caminho para código complexo já está lá, isso é muito mais simples.


7
Você esqueceu de adicionar break;quando o índice for encontrado para acelerar o processo.
Spacebiker # 28/13

por que não usar do {} while () para evitar o uso de break?
precisa saber é o seguinte

@Catluc existem n número de maneiras para se chegar a uma solução, você escolhe ... o que funciona melhor para você
Akhil Jain

4
Em vez de 0, você deve retornar -1se o valor não for encontrado - como mostrado na minha resposta: stackoverflow.com/a/32377917/1617737 :-)
ban-geoengenharia

2
@ ban-geoengineering eu escrevi 0como cenário de backup. Se você definir -1qual item seria visível no girador, suponho que o 0º elemento do adaptador giratório, a adição de -1 também adicione excesso de peso para verificar se o valor é -1 ou não, pois a configuração -1 causará exceção.
Akhil Jain

34

Eu mantenho uma ArrayList separada de todos os itens em meus Spinners. Dessa forma, eu posso fazer indexOf no ArrayList e, em seguida, usar esse valor para definir a seleção no Spinner.


Não há outra maneira, você sabe?
usar o seguinte comando

1
Como definir a seleção para nada? (se o item não estiver na lista)
Pentium10

5
HashMap.get daria uma melhor velocidade de pesquisa de ArrayList.indexOf
Dandre Allison

29

Com base na resposta da Merrill , eu vim com essa solução de linha única ... não é muito bonita, mas você pode culpar quem mantém o código Spinnerpor negligenciar a inclusão de uma função que faz isso para isso.

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

Você receberá um aviso sobre como o elenco de um ArrayAdapter<String>é desmarcado ... realmente, você pode simplesmente usar um ArrayAdaptercomo Merrill, mas isso apenas troca um aviso por outro.


Para se livrar do aviso desmarcado, você deve usar <? > no elenco, em vez de <>. De fato, sempre que você converter algo com um tipo, você deve usar <? >.
precisa saber é o seguinte

Não, se eu converter para <? > gera um erro em vez de um aviso: "O método getPosition (?) no tipo ArrayAdapter <?> não é aplicável ao argumento (String)."
ArtOfWarfare 30/08/2012

Correto, ele pensará que é um ArrayAdapter sem tipo, portanto não assumirá que é um ArrayAdapter <>. Portanto, para evitar o aviso, você precisará convertê-lo em ArrayAdapter <? > então converta o resultado do seu adapter.get () para uma String.
xbakesx

@ Dadani - Presumo que você nunca usou Python antes, porque isso é estupidamente complicado.
ArtOfWarfare 13/09/2015

Concordo, não brinquei com o Python @ArtOfWarfare, mas esse é um caminho rápido para determinadas tarefas.
Daniel Daniel

13

se você estiver usando um array de strings, esta é a melhor maneira:

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

10

Você pode usar isso também,

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

Trabalho brilhante!
21419 Sadman Hasan

8

Se você precisar ter um método indexOf em qualquer adaptador antigo (e não souber a implementação subjacente), poderá usar o seguinte:

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

Com base na resposta da Merrill, aqui está como fazer com um 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 a seguinte linha para selecionar usando o valor:

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

3

Estou usando um adaptador personalizado, para que esse código seja suficiente:

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

Portanto, seu snippet de código será assim:

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

3

Este é o meu método simples de obter o índice por string.

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

Você pode usar dessa maneira, basta tornar seu código mais simples e mais claro.

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

Espero que ajude.


2

aqui está a minha solução

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 abaixo

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 esta ajuda!


2

Aqui está como fazer isso se você estiver usando um SimpleCursorAdapter(onde columnNameé o nome da coluna db que você usou para preencher o seu 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;
    }
}

Além disso (um refinamento da resposta de Akhil ), esta é a maneira correspondente de fazer isso se você estiver preenchendo seu Spinner a partir de uma 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

Se você definir uma matriz XML para o controle giratório no layout XML, poderá fazer isso

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

Na verdade, existe uma maneira de fazer isso usando uma pesquisa de índice no AdapterArray e tudo isso pode ser feito com reflexão. Eu mesmo fui um passo além, pois tinha 10 Spinners e queria defini-los dinamicamente no meu banco de dados, e o banco de dados mantém o valor apenas não o texto, pois o Spinner realmente muda semana a semana, então o valor é o meu número de identificação do banco de dados.

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

}

Aqui está a pesquisa indexada que você pode usar em praticamente qualquer lista, desde que os campos estejam no nível superior do 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
}

O método de conversão que pode ser criado para todas as primitivas aqui é um 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 fazer com que o aplicativo se lembre dos últimos valores selecionados do girador, você pode usar o código abaixo:

  1. O código abaixo lê o valor do girador e define a posição do girador de acordo.

    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 insira o código abaixo, onde você sabe que os valores mais recentes do girador estão presentes ou em outro lugar, conforme necessário. Esse trecho de código basicamente grava o valor do spinner em 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

Eu tive o mesmo problema ao tentar selecionar o item correto em um girador preenchido usando um cursorLoader. Recuperei o ID do item que desejava selecionar primeiro da tabela 1 e, em seguida, usei um CursorLoader para preencher o botão giratório. No onLoadFinished, passei pelo cursor preenchendo o adaptador do girador até encontrar o item que correspondia ao ID que já tinha. Em seguida, atribua o número da linha do cursor à posição selecionada do girador. Seria bom ter uma função semelhante para passar o ID do valor que você deseja selecionar no botão giratório ao preencher detalhes em um formulário contendo resultados salvos do botão giratório.

@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 algumas das respostas anteriores estão muito corretas, só quero garantir que nenhum de vocês caia nesse problema.

Se você definir os valores para o ArrayListuso String.format, você DEVE obter a posição do valor usando a mesma estrutura de string String.format.

Um exemplo:

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

Você deve obter a posição do valor necessário assim:

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

Caso contrário, você obterá o -1item não encontrado!

Eu usei Locale.getDefault()por causa da língua árabe .

Espero que seja útil para você.


0

Aqui está minha solução esperançosamente completa. Eu tenho o seguinte enum:

public enum HTTPMethod {GET, HEAD}

usado na classe a seguir

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

Código para definir o controle giratório 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);

Onde R.id.spinnerHttpmethodé definido em um arquivo de layout e android.R.layout.simple_spinner_itemé entregue pelo 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);
        }
    }

Bem-vindo ao StackOverflow. Respostas com apenas código nelas tendem a ser sinalizadas para exclusão por serem de "baixa qualidade". Leia a seção de ajuda para responder perguntas e considere adicionar alguns comentários à sua resposta.
Graham

@ user2063903, adicione explicação na sua resposta.
LUFFY

0

muito simples é só usar getSelectedItem();

por exemplo :

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

o método acima retorna um valor de sequência

acima, R.array.admin_typehá um arquivo de recursos de string em valores

basta criar um arquivo .xml em values ​​>> strings


0

Suponha que você precise preencher o botão giratório a partir da matriz de cadeias de caracteres do recurso e deseja manter o valor selecionado no servidor. Portanto, essa é uma maneira de definir um valor selecionado do servidor no botão rotativo.

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

Espero que ajude! PS o código está em Kotlin!


0

Como eu precisava de algo que também funciona com Localização , criei esses dois 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 você pode ver, também me deparei com uma complexidade adicional de distinção entre maiúsculas e minúsculas entre arrays.xml e a valueque estou comparando. Se você não tiver isso, o método acima pode ser simplificado para 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

você precisa passar seu adaptador personalizado com uma posição como REPEAT [posição]. e funciona corretamente.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.