如何通过值而不是位置来设置微调框的选定项目?


295

我有一个更新视图,在这里我需要预选存储在数据库中的Spinner值。

我当时的想法是这样的,但是Adapter没有indexOf方法,所以我陷入了困境。

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

Answers:


643

假设您Spinner的名称为mSpinner,并且其中包含以下选项之一:“某个值”。

要查找和比较微调器中“某些值”的位置,请使用以下命令:

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 2012年

3
如果您不是检查字符串而是对象内部的元素,那怎么办?不可能仅使用toString()导致微调器的值与toString()的输出有所不同。
阿吉波拉

1
我知道这很老了,但是现在抛出了一个未经检查的getPosition(T)调用
Brad Bass

抛出了类似的错误,但是使用这种传统的方法有所帮助: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;找到索引后,您忘了添加以加快处理过程。
2013年

为什么不使用do {} while()来避免使用break?
Catluc '16

@Catluc有n种方法可以找到解决方案,您选择...最适合您的方法
Akhil Jain

4
而不是0-1如果找不到该值,您应该返回-如我的答案所示:stackoverflow.com/a/32377917/1617737 :-)
ban-geoengineering

2
@ ban-geoengineering我写0为备份方案。如果设置-1,在微调框上将显示什么项目,我假设微调框适配器的第0个元素,添加-1还会增加检查值是否为-1的超重,导致设置-1将导致异常。
Akhil Jain

34

我在微调器中保留了所有项目的单独ArrayList。这样,我可以在ArrayList上执行indexOf,然后使用该值在Spinner中设置选择。


您知道别无其他方法吗?
Pentium10年

1
如何将选择设置为空?(如果该项目不在列表中)
Pentium10年

5
HashMap.get将比ArrayList.indexOf提供更好的查找速度
Dandre Allison 2012年

29

根据Merrill的回答,我想出了这种单行解决方案……虽然不是很漂亮,但是您可以责怪维护代码Spinner的人忽视了包含为此功能的函数。

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

您将收到有关如何ArrayAdapter<String>取消强制转换为a的警告...确实,您可以ArrayAdapter像Merrill一样使用a ,但这只是将一个警告换成另一个。


要摆脱未经检查的警告,应使用<?>,而不是<String>。实际上,任何时候使用类型转换任何内容时,都应该使用<?>。
xbakesx 2012年

不,如果我强制使用<?它给了我一个错误而不是一个警告:“ ArrayAdapter <?>类型的方法getPosition(?)不适用于参数(字符串)。”
ArtOfWarfare 2012年

正确,然后它将认为它是没有类型的ArrayAdapter,因此不会假定它是ArrayAdapter <String>。因此,为了避免警告,您需要将其强制转换为ArrayAdapter <?>然后将您的adapter.get()的结果强制转换为字符串。
xbakesx 2012年

@Dadani-我认为您以前从未使用过Python,因为这令人费解。
ArtOfWarfare

同意,我还没有使用Python @ArtOfWarfare,但这是完成某些任务的快速方法。
Daniel Dut 2015年

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

辉煌的工作!
Sadman Hasan

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


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

如果您使用的是SimpleCursorAdaptercolumnName用来填充的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;
    }
}

另外(对Akhil的答案进行了细化),这是从数组填充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个Spinners,并希望从数据库中动态设置它们,并且由于Spinner实际上每周都在变化,因此数据库仅保留值而不是文本,因此该值是我从数据库获得的ID号。

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

可以为所有原语创建的强制转换方法是用于string和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. 并在下面的代码中找到您知道最新微调器值的位置,或放置在所需的其他位置。这段代码基本上将Spinner值写入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中检索了我想首先选择的项目的ID,然后使用CursorLoader填充了微调器。在onLoadFinished中,我循环浏览了填充微调器适配器的光标,直到找到与我已有的ID匹配的项。然后将光标的行号分配给微调器的所选位置。当在包含已保存的微调器结果的表单上填充详细信息时,具有类似的函数来传递您希望在微调器中选择的值的ID将是很好的。

@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

由于前面的某些答案是非常正确的,所以我只想确保你们所有人都不会陷入这种问题。

如果将值设置为ArrayListusing 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;
...

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

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.