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);
}
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);
}
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.
break;
when the index is found to speed up the process.
0
, you should return -1
if the value is not found - as shown in my answer: stackoverflow.com/a/32377917/1617737 :-)
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.
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.
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.
if you are using string array this is the best way:
int selectionPosition= adapter.getPosition("YOUR_VALUE");
spinner.setSelection(selectionPosition);
Use following line to select using value:
mSpinner.setSelection(yourList.indexOf("value"));
You can use this also,
String[] baths = getResources().getStringArray(R.array.array_baths);
mSpnBaths.setSelection(Arrays.asList(baths).indexOf(value_here));
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;
}
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;
}
}
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.
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!
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));
}
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;
}
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
}
};
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!
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);
}
}
}
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<Device> needs to be passed as a List<Object> or Object[ ] by using
* Arrays.asList(device.toArray( )).
*
* @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;
}
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
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
}
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.
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.
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);
}
}
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
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();
}
you have to pass your custom adapter with position like REPEAT[position]. and it works properly.
Success story sharing