ChatGPT解决这个技术问题 Extra ChatGPT

如何按值而不是按位置设置 Spinner 的选定项?

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

我有这样的想法,但 Adapter 没有 indexOf 方法,所以我被卡住了。

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

K
Kunwar Ajeet Singh Rajput

假设您的 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);
}

使用自定义适配器,您必须编写(覆盖) getPosition() 的代码
如果您不是检查字符串而是检查对象内的元素,并且不可能只使用 toString() 会导致微调器的值与 toString() 的输出不同。
我知道这已经很老了,但是现在这会引发对 getPosition(T) 的未经检查的调用
抛出了类似的错误,但使用这种老派的方法有帮助:stackoverflow.com/questions/25632549/…
嗯...现在,如果我从 Parse.com 中提取值,并且想要查询用户以便默认微调器选择默认为用户的数据库值,该怎么办?
Z
Zon

根据值设置微调器的一种简单方法是

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

复杂代码的方式已经存在,这更简单。


发现索引时忘记添加 break; 以加快处理速度。
为什么不使用 do{}while() 来避免使用 break?
@Catluc 有多种方法可以找到解决方案,您可以选择...最适合您的方法
如果找不到该值,您应该返回 -1 而不是 0 - 如我的回答所示:stackoverflow.com/a/32377917/1617737 :-)
@ban-geoengineering 我写了 0 作为备份方案。如果设置-1,在微调器上会看到什么项目,我假设微调器适配器的第 0 个元素,添加 -1 也会增加检查值是否为 -1 的权重,因为设置 -1 会导致异常。
A
Abishek Stephen

基于 Merrill's answer,我提出了这个单行解决方案......它不是很漂亮,但你可以责怪维护 Spinner 代码的人忽略了包含为此执行此操作的函数。

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

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

如果警告导致问题,只需添加

@SuppressWarnings("unchecked")

到方法签名或声明之上。


要摆脱未经检查的警告,您应该使用 < ? > 在你的演员阵容中,而不是 。事实上,任何时候你用类型转换任何东西,你都应该使用 < ? >。
不,如果我转换为 < ? > 它给了我一个错误而不是警告:“类型 ArrayAdapter 中的方法 getPosition(?) 不适用于参数 (String)。”
正确,它会认为它是一个没有类型的 ArrayAdapter,所以它不会假设它是一个 ArrayAdapter。因此,为了避免警告,您需要将其强制转换为 ArrayAdapter< ? > 然后将 adapter.get() 的结果转换为字符串。
@Dadani - 我认为你以前从未使用过 Python,因为这非常复杂。
这非常干净,并且与视图绑定配合得很好。 binding.spinner.setSelection(((ArrayAdapter)binding.spinner.getAdapter()).getPosition(pojo.spinnerValue));谢谢
M
Mark B

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


没有别的办法,你知道吗?
如何将选择设置为空? (如果该项目不在列表中)
HashMap.get 会比 ArrayList.indexOf 提供更好的查找速度
i
itzhar

如果您使用的是字符串数组,这是最好的方法:

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

F
Faisal Shaikh

使用以下行选择使用值:

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

P
PrvN

你也可以用这个,

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

x
xbakesx

如果您需要在任何旧适配器上有一个 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;
}

m
max4ever

根据 Merrill 的回答,这里是如何使用 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

你可以使用这种方式,只是让你的代码更简单,更清晰。

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

希望能帮助到你。


S
Scott.N

这是我的解决方案

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

希望这有帮助!


M
Miral Sarwar

我正在使用自定义适配器,因为这段代码就足够了:

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

因此,您的代码片段将如下所示:

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

a
aLIEz

这是我通过字符串获取索引的简单方法。

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

如果您使用 SimpleCursorAdapter(其中 columnName 是您用来填充 spinner 的 db 列的名称),请按以下步骤操作:

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's answer 的改进)如果您从数组中填充 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
    }
};

h
hetsgandhi

假设您需要从资源的字符串数组中填充微调器,并且您希望保留从服务器中选择的值。因此,这是在微调器中设置从服务器中选择的值的一种方法。

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

希望能帮助到你! PS 代码在 Kotlin 中!


L
Lasitha Lakmal

如果您将 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);
      }
   }
}

J
JPM

实际上有一种方法可以使用 AdapterArray 上的索引搜索来获得它,所有这些都可以通过反射来完成。我什至更进一步,因为我有 10 个 Spinner,并且想从我的数据库中动态设置它们,并且数据库只保存值而不是文本,因为 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
}

可以在这里为所有原语创建的 Cast 方法是用于 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;
}

u
user3339073

要使应用程序记住最后选择的微调器值,您可以使用以下代码:

下面的代码读取微调器值并相应地设置微调器位置。公共类 MainActivity 扩展 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); // 将适配器应用到微调器 spinner1.setAdapter(adapter1); // 更改以记住最后一个微调器位置 spinnerPosition = 0;字符串 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);微调器位置 = 0;并将下面的代码放在你知道最新微调器值存在的地方,或者根据需要放在其他地方。这段代码基本上是在 SharedPreferences 中写入 spinner 的值。 Spinner spinner1 = (Spinner) findViewById(R.id.spinner1);字符串 spinlong1 = spinner1.getSelectedItem().toString(); SharedPreferences prfs = getSharedPreferences("WHATEVER", Context.MODE_PRIVATE); SharedPreferences.Editor 编辑器 = prfs.edit(); editor.putString("SPINNER1_VALUE", spinlong1); editor.commit();


b
bummi

尝试在使用 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

}

M
Mohammed AlBanna

由于之前的一些答案是非常正确的,我只想确保你们没有人陷入这样的问题。

如果使用 String.format 将值设置为 ArrayList,则必须使用相同的字符串结构 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()

我希望这对你有帮助。


t
termigrator

这是我希望的完整解决方案。我有以下枚举:

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

其中 R.id.spinnerHttpmethod 在布局文件中定义,android.R.layout.simple_spinner_item 由 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);
        }
    }

欢迎来到 StackOverflow。其中只有代码的答案往往会被标记为删除,因为它们是“低质量”的。请阅读有关回答问题的帮助部分,然后考虑在您的答案中添加一些评论。
@ user2063903,请在您的答案中添加解释。
D
Dima Kozhevin

非常简单,只需使用 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 是值中的字符串资源文件

只需在 values>>strings 中创建一个 .xml 文件


A
AZOM

因为我需要一些也适用于本地化的东西,所以我想出了这两种方法:

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

U
Urvi Jasani

你必须通过像 REPEAT[position] 这样的位置来传递你的自定义适配器。它工作正常。