Як встановити вибраний елемент Spinner за значенням, а не за позицією?


296

У мене є перегляд оновлень, де мені потрібно попередньо вибрати значення, збережене в базі даних для Spinner.

Я мав на увазі щось подібне, але методу Adapterнемає indexOf, тому я застряг.

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

Відповіді:


644

Припустимо, ваш Spinnerназваний mSpinner, і він містить один із його варіантів: "деяке значення".

Щоб знайти і порівняти позицію "деякого значення" в Spinner, використовуйте це:

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
за допомогою спеціального адаптера вам доведеться написати (замінити) код для getPosition ()
Soham

3
Як щодо того, якщо ви не перевіряєте рядок, а елемент всередині об'єкта, і не можна просто використовувати toString (), тому що значення спінера залежить від виходу toString ().
Аджибола

1
Я знаю, що це дуже старе, але це зараз кидає неперевірений дзвінок на getPosition (T)
Бред Басс

що подібні помилки викинуті, але з допомогою цього старої школи шляху допомогли: stackoverflow.com/questions/25632549 / ...
Manny265

Хм ... А що робити, якщо я витягую значення з, скажімо, Parse.com, і хочу запитати користувача, щоб вибір спінера за замовчуванням був встановлений за замовчуванням до бази даних користувача?
drearypanoramic

141

Простий спосіб встановити спінер на основі значення

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

Шлях до складного коду вже є, це просто набагато простіше.


7
Ви забули додати, break;коли буде виявлено, що індекс прискорить процес.
космічний байкер

чому б не використовувати do {} while (), щоб уникнути використання перерви?
Catluc

@Catluc існує п ять способів досягти рішення, ви вибираєте ... що найкраще підходить для вас
Ахіл Джайн

4
Замість цього 0вам слід повернути, -1якщо значення не знайдено - як показано у моїй відповіді: stackoverflow.com/a/32377917/1617737 :-)
заборона-геоінженерія

2
@ ban-geoengineering Я написав 0як резервний сценарій. Якщо ви встановите -1, який елемент буде видно на спінері, я вважаю, що 0-й елемент адаптера спінера, додавання -1 також додає зайву вагу, перевіряючи, чи є значення -1 чи ні, тому що встановлення -1 спричинить виключення.
Ахіл Джайн

34

Я зберігаю окремий ArrayList всіх елементів у моїх Spinners. Таким чином я можу зробити indexOf на ArrayList, а потім використати це значення для встановлення вибору в Spinner.


Немає іншого шляху, ви знаєте?
Pentium10

1
Як встановити вибір на нічого? (якщо товару немає в списку)
Pentium10

5
HashMap.get дав би кращу швидкість пошуку, ніж ArrayList.indexOf
Dandre Allison

29

Виходячи з відповіді Меррілла , я придумав це рішення для єдиного рядка ... це не дуже красиво, але ви можете звинувачувати того, хто підтримує код Spinnerза те, що він нехтував, включаючи функцію, яка робить це для цього.

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

Ви отримаєте попередження про те, як передача на ArrayAdapter<String>атрибути не перевірена ... Дійсно, ви можете просто використовувати так, ArrayAdapterяк це зробила Меррилл, але це просто обміняється одним попередженням на інше.


Щоб позбутися неперевіреного попередження, слід використовувати <? > у твоєму складі замість <String>. Насправді, кожного разу, коли ви передаєте щось із типом, ви повинні використовувати <? >.
xbakesx

Ні, якщо я кидаю на <? > це дає мені помилку замість попередження: "Метод getPosition (?) типу ArrayAdapter <?> не застосовується для аргументу (String)."
ArtOfWarfare

Правильно, тоді він подумає, що це ArrayAdapter без типу, тому не буде вважати, що це ArrayAdapter <String>. Отже, щоб уникнути попередження, вам потрібно буде передавати його ArrayAdapter <? > потім киньте результат свого adapter.get () у рядок.
xbakesx

@Dadani - Я вважаю, що ви ніколи раніше не використовували Python, тому що це нерозумно.
ArtOfWarfare

Погоджено, я не грав з Python @ArtOfWarfare, але це швидкий шлях для певних завдань.
Даніель Дат

13

якщо ви використовуєте рядковий масив, це найкращий спосіб:

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

10

Ви також можете використовувати це,

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

Блискуча робота!
Садман Хасан

8

Якщо вам потрібно мати метод indexOf на будь-якому старому адаптері (і ви не знаєте основної реалізації), ви можете використовувати це:

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

Виходячи з відповіді Меррілла тут, як це зробити з 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

Для вибору значення використовуйте наступний рядок:

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

3

Я використовую спеціальний адаптер, для цього цього коду достатньо:

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

Отже, ваш фрагмент коду буде таким:

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

3

Це мій простий метод отримати індекс по рядку.

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

Ви можете використовувати цей спосіб, просто зробіть свій код більш простим і зрозумілим.

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

Сподіваюся, це допомагає.


2

ось моє рішення

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

та getItemIndexById нижче

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

Сподіваюся, що це допоможе!


2

Ось як це зробити, якщо ви використовуєте SimpleCursorAdapter(де columnNameназва стовпця db, який ви використовували для заповнення 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;
    }
}

Також (уточнення відповіді Ахіла ) це відповідний спосіб зробити це, якщо ви заповнюєте Spinner з масиву:

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

Якщо ви встановите масив XML для спінера в макеті XML, ви можете це зробити

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

Насправді існує спосіб отримати це за допомогою пошуку в індексі на AdapterArray, і все це можна зробити за допомогою відображення. Я навіть пішов на крок далі, оскільки у мене було 10 спінерів і хотів динамічно встановити їх у моїй базі даних, і база даних містить значення не лише тексту, оскільки Spinner фактично змінюється тиждень на тиждень, тому значення - це мій ідентифікаційний номер із бази даних.

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

}

Ось індексований пошук, який ви можете використовувати майже в будь-якому списку, поки поля знаходяться на верхньому рівні об'єкта.

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

Метод лиття, який можна створити для всіх примітивів, тут - це метод для рядка та 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

Щоб програма пам’ятала останні вибрані значення спінера, ви можете використовувати код нижче:

  1. Нижче код зчитує значення спінера і відповідно встановлює позицію спінера.

    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. І введіть нижче код, де ви знаєте, що останні світильники знаходяться, або деінде, як потрібно. Цей фрагмент коду в основному записує значення спінера в 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

У мене була така ж проблема, коли я намагався вибрати правильний елемент у спінері, заселеному за допомогою cursorLoader. Я отримав ідентифікатор елемента, який хотів спочатку вибрати з таблиці 1, а потім використав CursorLoader для заповнення спінера. У програмі onLoadFinished я проїхав курсор, заповнюючи адаптер спінера, поки не знайшов елемент, який відповідав ідентифікатору, який я вже мав. Потім присвоїли номер рядка курсору вибраному положенню. Було б непогано мати подібну функцію, щоб передати ідентифікатор значення, яке ви хочете вибрати у спінері, коли заповнюєте деталі у формі, що містить збережені результати спінера.

@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

Оскільки деякі попередні відповіді дуже правильні, я просто хочу переконатися, що ніхто з вас не потрапить у таку проблему.

Якщо ви встановите значення у ArrayListвикористанні String.format, ОБОВ'ЯЗКОВО отримати положення значення за допомогою тієї ж струнної структури String.format.

Приклад:

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

Ви повинні отримати позицію потрібного значення, як це:

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

В іншому випадку ви отримаєте -1товар, який не знайдено!

Я використовував Locale.getDefault()через арабську мову .

Я сподіваюся, що це буде вам корисно.


0

Ось моє сподівання повне рішення. У мене є наступний перелік:

public enum HTTPMethod {GET, HEAD}

використовується в наступному класі

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

Код для встановлення віджимання за рахунок enTP-члена HTTPMethod:

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

Де R.id.spinnerHttpmethodвизначено у файлі макета, а android.R.layout.simple_spinner_itemвін доставляється 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);
        }
    }

Ласкаво просимо до StackOverflow. Відповіді, що містять лише код, мають тенденцію до видалення, оскільки вони "низької якості". Прочитайте розділ довідки щодо відповіді на запитання, а потім подумайте, як додати свій коментар до своєї відповіді.
Грем

@ user2063903, Будь ласка, додайте пояснення у відповідь.
LuFFy

0

дуже просто просто використовувати getSelectedItem();

наприклад:

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

вищевказаний метод повертає значення рядка

у наведеному вище R.array.admin_type- це рядовий файл ресурсів у значеннях

просто створіть .xml файл у рядках значень >>


0

Припустимо, вам потрібно заповнити спінер з рядкового масиву з ресурсу, і ви хочете зберегти вибране значення з сервера. Отже, це один із способів встановити вибране значення з сервера в спінері.

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

Сподіваюся, це допомагає! PS код знаходиться в Котліні!


0

Оскільки мені було потрібно щось, що також працює з Локалізацією , я придумав ці два методи:

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

Як ви бачите, я також натрапив на додаткову складність чутливості регістру між arrays.xml і valueпорівнянням. Якщо у вас цього немає, описаний вище метод можна спростити до чогось подібного:

return arrayValues.indexOf(value);

Статичний хелперний метод

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

ви повинні передати свій користувальницький адаптер у такому положенні, як REPEAT [position]. і він працює належним чином.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.