ChatGPT解决这个技术问题 Extra ChatGPT

How to set selected item of Spinner by value, not by position?

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

K
Kunwar Ajeet Singh Rajput

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

with a custom adapter you will have to write (override) the code for getPosition()
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().
I know this is very old, but this now throws an unchecked call to getPosition(T)
had similar errors thrown,but using this old school way helped: stackoverflow.com/questions/25632549/…
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?
Z
Zon

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.


You forgot to add break; when the index is found to speed up the process.
why not use do{}while() to avoid using break?
@Catluc there are n number of ways to arrive at solution, you choose ...what works best for you
Rather than 0, you should return -1 if the value is not found - as shown in my answer: stackoverflow.com/a/32377917/1617737 :-)
@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.
A
Abishek Stephen

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.


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 < ? >.
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)."
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.
@Dadani - I take it you've never used Python before, because this is stupidly convoluted.
This was very clean, and worked well with view binding. binding.spinner.setSelection(((ArrayAdapter)binding.spinner.getAdapter()).getPosition(pojo.spinnerValue)); Thanks @A
M
Mark B

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.


There is no other way, you know of?
How to set selection to nothing? (if the item is not in the list)
HashMap.get would give better lookup speed than ArrayList.indexOf
i
itzhar

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

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

F
Faisal Shaikh

Use following line to select using value:

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

P
PrvN

You can use this also,

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

x
xbakesx

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

m
max4ever

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

a
azwar_akbar

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.


S
Scott.N

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!


M
Miral Sarwar

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

a
aLIEz

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

b
ban-geoengineering

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

h
hetsgandhi

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!


L
Lasitha Lakmal

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

J
JPM

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

u
user3339073

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

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


b
bummi

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

}

M
Mohammed AlBanna

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.


t
termigrator

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.


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

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.
@user2063903, Please add explanation in your answer.
D
Dima Kozhevin

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


A
AZOM

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

U
Urvi Jasani

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