341

I have a update view, where I need to preselect the value stored in database for a Spinner.

I was having in mind something like this, but the Adapter has no indexOf method, so I am stuck.

void setSpinner(String value)
{
    int pos = getSpinnerField().getAdapter().indexOf(value);
    getSpinnerField().setSelection(pos);
}
thyago stall
  • 1,654
  • 3
  • 16
  • 30
Pentium10
  • 204,586
  • 122
  • 423
  • 502

25 Answers25

704

Suppose your Spinner is named mSpinner, and it contains as one of its choices: "some value".

To find and compare the position of "some value" in the Spinner use this:

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);
}
Merrill
  • 7,088
  • 2
  • 15
  • 3
  • 6
    with a custom adapter you will have to write (override) the code for getPosition() – Soham Dec 26 '12 at 12:57
  • 3
    How about if you are not checking against a string but an element inside an object and it isnt possible to just use the toString() cause the value of the spinner varies from the output of toString(). – Ajibola Mar 06 '13 at 09:57
  • 1
    I know this is very old, but this now throws an unchecked call to getPosition(T) – Brad Bass Oct 02 '14 at 12:40
  • had similar errors thrown,but using this old school way helped: http://stackoverflow.com/questions/25632549/how-do-i-set-spinner-value-based-on-the-value-in-preferences – Manny265 Sep 14 '15 at 20:23
  • Hmm... Now what if I'm pulling the value from, say, Parse.com, and want to query the user so that the default spinner selection is defaulted to the user's database value? – drearypanoramic Oct 16 '15 at 21:31
  • @Merrill I am having a similar problem please check if you can be of help on http://stackoverflow.com/q/35367172/2595059 Thanks – George Feb 12 '16 at 16:44
  • string.equals(null) usually trhow a NullPointerException when string is null, instead use string!=null to avoid this – Leonardo Sapuy Jun 22 '17 at 15:26
157

A simple way to set spinner based on value is

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

Way to complex code are already there, this is just much plainer.

Zon
  • 18,610
  • 7
  • 91
  • 99
Akhil Jain
  • 13,872
  • 15
  • 57
  • 93
  • 10
    You forgot to add `break;` when the index is found to speed up the process. – spacebiker Nov 28 '13 at 12:09
  • why not use do{}while() to avoid using break? – Catluc Aug 29 '16 at 10:42
  • 1
    @Catluc there are n number of ways to arrive at solution, you choose ...what works best for you – Akhil Jain Aug 29 '16 at 12:13
  • 6
    Rather than `0`, you should return `-1` if the value is not found - as shown in my answer: http://stackoverflow.com/a/32377917/1617737 :-) – ban-geoengineering Sep 20 '16 at 11:26
  • 3
    @ban-geoengineering I wrote `0` as backup scenario. If you set `-1`, what item would be visible at spinner,i suppose the 0th element of spinner adapter, adding -1 also adds overweight of checking whether value is -1 or not, cause setting -1 will cause exception. – Akhil Jain Sep 20 '16 at 12:00
  • '-1' is the convention in Java for not found, so it is correct to check for `-1`. In this case, if `-1` is detected, then don't call `setSelection()` - as you could select/show the wrong thing to the user! – ban-geoengineering Sep 20 '16 at 12:18
  • Perfect because don't use ArrayAdapter (which is available at API level 21) – WizardingStudios Feb 19 '17 at 16:35
  • Returning `0` and returning `-1` both have merits. `0` allows you to simply call the function knowing the first item (usually the default) will be set if the passed element isn't found, but makes it harder to respond to an element not being found (since 0 could be a possible index for the element). `-1` makes it easy to respond to the element not existing, but also forces you to handle that case. One solution is to change the signature to `getIndex(Spinner spinner, String myString, int defaultValue)` and then `return defaultValue;` at the end. This allows either implementation (among others). – VerumCH Apr 19 '18 at 09:18
  • How would this work with localization? In my case the spinner items are localized and like this it breaks for any other language than English. Because `spinner.getItemAtPosition(i).toString()` returns a localized string, where my comparison value `myString` expects always English localization (the way String keys are sent to the server) – AZOM Apr 26 '19 at 12:02
40

Based on Merrill's answer, I came up with this single line solution... it's not very pretty, but you can blame whoever maintains the code for Spinner for neglecting to include a function that does this for that.

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

You'll get a warning about how the cast to a ArrayAdapter<String> is unchecked... really, you could just use an ArrayAdapter as Merrill did, but that just exchanges one warning for another.

If the warning causes issue, just add

@SuppressWarnings("unchecked")

to the method signature or above the statement.

Abishek Stephen
  • 386
  • 1
  • 3
  • 15
ArtOfWarfare
  • 20,617
  • 19
  • 137
  • 193
  • To get rid of the unchecked warning you should use < ? > in your cast instead of . In fact any time you cast anything with a type, you should be using < ? >. – xbakesx Aug 29 '12 at 22:22
  • No, if I cast to a < ? > it gives me an error instead of a warning: "The method getPosition(?) in the type ArrayAdapter< ? > is not applicable for the argument (String)." – ArtOfWarfare Aug 30 '12 at 15:17
  • Correct, it will then think it's an ArrayAdapter with no type, so it will not assume it's an ArrayAdapter. So to avoid the warning you will need to cast it to ArrayAdapter< ? > then cast the result of your adapter.get() to a String. – xbakesx Aug 30 '12 at 17:57
  • @Dadani - I take it you've never used Python before, because this is stupidly convoluted. – ArtOfWarfare Sep 13 '15 at 01:07
  • Agreed, I haven't played around with Python @ArtOfWarfare, but this is a quick way for certain tasks. – Dut A. Sep 13 '15 at 01:39
  • 1
    This was very clean, and worked well with view binding. binding.spinner.setSelection(((ArrayAdapter)binding.spinner.getAdapter()).getPosition(pojo.spinnerValue)); Thanks @A – Sasquatch Dec 24 '20 at 13:42
36

I keep a separate ArrayList of all the items in my Spinners. This way I can do indexOf on the ArrayList and then use that value to set the selection in the Spinner.

Mark B
  • 183,023
  • 24
  • 297
  • 295
13

if you are using string array this is the best way:

int selectionPosition= adapter.getPosition("YOUR_VALUE");
spinner.setSelection(selectionPosition);
itzhar
  • 12,743
  • 6
  • 56
  • 63
11

Use following line to select using value:

mSpinner.setSelection(yourList.indexOf("value"));
Faisal Shaikh
  • 3,900
  • 5
  • 40
  • 77
10

You can use this also,

String[] baths = getResources().getStringArray(R.array.array_baths);
mSpnBaths.setSelection(Arrays.asList(baths).indexOf(value_here));
PrvN
  • 2,385
  • 6
  • 28
  • 30
8

If you need to have an indexOf method on any old Adapter (and you don't know the underlying implementation) then you can use this:

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;
}
xbakesx
  • 13,202
  • 6
  • 48
  • 76
7

Based on Merrill's answer here is how to do with a 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;
        }
    }
max4ever
  • 11,909
  • 13
  • 77
  • 115
4

You can use this way, just make your code more simple and more clear.

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

Hope it helps.

azwar_akbar
  • 1,451
  • 18
  • 27
3

here is my solution

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

and getItemIndexById below

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

Hope this help!

Scott.N
  • 172
  • 2
  • 17
3

I am using a custom adapter, for that this code is enough:

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

So, your code snippet will be like this:

void setSpinner(String value)
    {
         yourSpinner.setSelection(arrayAdapter.getPosition(value));
    }
Miral Sarwar
  • 327
  • 6
  • 12
3

This is my simple method to get the index by 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;
}
aLIEz
  • 1,206
  • 1
  • 15
  • 17
2

Here is how to do it if you are using a SimpleCursorAdapter (where columnName is the name of the db column that you used to populate your 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;
    }
}

Also (a refinement of Akhil's answer) this is the corresponding way to do it if you are filling your Spinner from an 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
    }
};
ban-geoengineering
  • 18,324
  • 27
  • 171
  • 253
2

Suppose you need to fill the spinner from the string-array from the resource, and you want to keep selected the value from server. So, this is one way to set selected a value from server in the spinner.

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

Hope it helps! P.S. the code is in Kotlin!

hetsgandhi
  • 726
  • 3
  • 9
  • 25
1

To make the application remember the last selected spinner values, you can use below code:

  1. Below code reads the spinner value and sets the spinner position accordingly.

    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. And put below code where you know latest spinner values are present, or somewhere else as required. This piece of code basically writes the spinner value 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();
    
1

If you set an XML array to the spinner in the XML layout you can do this

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);
      }
   }
}
Lasitha Lakmal
  • 486
  • 4
  • 17
0

I had the same issue when trying to select the correct item in a spinner populated using a cursorLoader. I retrieved the id of the item I wanted to select first from table 1 and then used a CursorLoader to populate the spinner. In the onLoadFinished I cycled through the cursor populating the spinner's adapter until I found the item that matched the id I already had. Then assigned the row number of the cursor to the spinner's selected position. It would be nice to have a similar function to pass in the id of the value you wish to select in the spinner when populating details on a form containing saved spinner results.

@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

}
bummi
  • 27,123
  • 14
  • 62
  • 101
Jaz
  • 371
  • 1
  • 6
  • 20
0

As some of the previous answers are very right, I just want to make sure from none of you fall in such this problem.

If you set the values to the ArrayList using String.format, you MUST get the position of the value using the same string structure String.format.

An example:

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

You must get the position of needed value like this:

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

Otherwise, you'll get the -1, item not found!

I used Locale.getDefault() because of Arabic language.

I hope that will be helpful for you.

Mohammed AlBanna
  • 2,350
  • 22
  • 25
0

Here is my hopefully complete solution. I have following enum:

public enum HTTPMethod {GET, HEAD}

used in following class

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

Code to set the spinner by 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);

Where R.id.spinnerHttpmethod is defined in a layout-file, and android.R.layout.simple_spinner_item is delivered by android-studio.

termigrator
  • 159
  • 3
  • 11
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);
        }
    }
Graham
  • 7,431
  • 18
  • 59
  • 84
  • Welcome to StackOverflow. Answers with only code in them tend to get flagged for deletion as they are "low quality". Please read the help section on answering questions then consider adding some commentary to your Answer. – Graham Feb 12 '18 at 03:45
  • @user2063903, Please add explanation in your answer. – LuFFy Feb 12 '18 at 06:56
0

very simple just use getSelectedItem();

eg :

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

the above method returns an string value

in the above the R.array.admin_type is an string resource file in values

just create an .xml file in values>>strings

Dima Kozhevin
  • 3,602
  • 9
  • 39
  • 52
pc expert
  • 1
  • 1
0

Since I needed something, that also works with Localization, I came up with these two methods:

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

As you can see, I also stumbled over additional complexity of case sensitivity between arrays.xml and the value I am comparing against. If you don't have this, the above method can be simplified to something like:

return arrayValues.indexOf(value);

Static helper method

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();
    }
AZOM
  • 265
  • 5
  • 15
0

There is actually a way to get this using an index search on the AdapterArray and all this can be done with reflection. I even went one step further as I had 10 Spinners and wanted to set them dynamically from my database and the database holds the value only not the text as the Spinner actually changes week to week so the value is my id number from the 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);

}

Here is the indexed search you can use on almost any list as long as the fields are on top level of object.

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

Cast method which can be create for all primitives here is one for string and 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;
}
JPM
  • 9,077
  • 13
  • 78
  • 137
-3

you have to pass your custom adapter with position like REPEAT[position]. and it works properly.