在下拉框中设置键和值

49

我有一个Spinner,我希望在它上面设置一个键和一个值,我使用了HashMap,它可以工作,但是只显示了一行,就像这样:

这里输入图片的描述

代码:

        final View rootView = inflater.inflate(R.layout.fragment_photos, container, false);

    Spinner spin=(Spinner)rootView.findViewById(R.id.spinner1);

    HashMap<Integer, String> P_Hash=new HashMap<Integer, String>();

    Update Get_Information=new Update(rootView.getContext());

    ArrayList<String> Province_NAME=new ArrayList<String>();
    Province_NAME=Get_Information.GET_Province();

    ArrayList<Integer> Province_ID=new ArrayList<Integer>();
    Province_ID=Get_Information.Get_Province_ID();

    for (int i = 0; i < Province_ID.size(); i++)
    {
        P_Hash.put(Province_ID.get(i), Province_NAME.get(i));
        Log.d("Province_ID.get(i)", Province_ID.get(i)+"");
        Log.d(" Province_NAME.get(i)",  Province_NAME.get(i)+"");
    }


    ArrayAdapter<HashMap<Integer, String>> adapter = new ArrayAdapter<HashMap<Integer,String>>(rootView.getContext(), android.R.layout.simple_spinner_item);
    adapter.add(P_Hash);
    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);

    spin.setAdapter(adapter);
3个回答

159

更好的方法来使用键值对填充下拉菜单应该是:

步骤1:创建POJO类,负责处理键和值。

public class Country {

    private String id;
    private String name;
    
    public Country(String id, String name) {
        this.id = id;
        this.name = name;
    }


    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }


    //to display object as a string in spinner
    @Override
    public String toString() {
        return name;
    }

    @Override
    public boolean equals(Object obj) {
        if(obj instanceof Country){
            Country c = (Country )obj;
            if(c.getName().equals(name) && c.getId()==id ) return true;
        }

        return false;
    }

}



注意: toString() 方法非常重要,因为它负责在下拉列表中显示数据,您可以根据需要修改 toString() 方法

步骤2: 准备要加载到下拉列表中的数据

 private void setData() {

        ArrayList<Country> countryList = new ArrayList<>();
        //Add countries

        countryList.add(new Country("1", "India"));
        countryList.add(new Country("2", "USA"));
        countryList.add(new Country("3", "China"));
        countryList.add(new Country("4", "UK"));

        //fill data in spinner 
        ArrayAdapter<Country> adapter = new ArrayAdapter<Country>(context, android.R.layout.simple_spinner_dropdown_item, countryList);
        spinner_country.setAdapter(adapter);
        spinner_country.setSelection(adapter.getPosition(myItem));//Optional to set the selected item.    
    }
步骤三: 在Spinner的onitemselected监听器方法中获取最终选定项的键和值。
spinner_country.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {

                 Country country = (Country) parent.getSelectedItem();
                 Toast.makeText(context, "Country ID: "+country.getId()+",  Country Name : "+country.getName(), Toast.LENGTH_SHORT).show();    
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {    
            }
        });

@SrinivasGuni 大佬,示例很棒。我需要帮助,请问为什么要重写 onItemSelected 方法呢?我尝试不覆盖它,但是没有起作用。你能帮我解决问题吗? - Jayanta
@jayanta 首先是个好问题。我们正在使用ArrayAdapter,它充当数据集(我们的国家列表)和适配器视图即Spinner的每一行之间的桥梁。因此,每当您想要为每一行选择启用单击侦听器时,必须覆盖AdapterView接口的onitemselected监听器。因此,每次单击Spinner的行时,都会调用此方法,并且您可以在单击该行时执行任何操作。希望这有所帮助。 - Srinivas Guni
你应该强调“toString()”方法部分,这是关键。我编辑了你的解释,希望有人接受我的修改。 - Dika
@Dika,我已经做了,你可以看到注释部分。也许你跳过了那一部分。 - Srinivas Guni
@SrinivasGuni 为什么要在POJO内重写equals方法?是为了能够在Spinner中设置选择吗?你能否在equals方法上方添加一段说明,解释为什么要进行重写? - RRGT19
1
@RRGT19 Equals方法有助于比较相同类型的对象,以便在ArrayList中不添加重复记录。你可以跳过equals方法。 - Srinivas Guni

92

尝试使用HashMap来存储键-值对数据,在您的情况下,将Spinner项目索引作为键,将Province_ID作为值。请查看下面的示例以了解更多详细信息。

为Spinner准备值

String[] spinnerArray = new String[Province_ID.size()];
HashMap<Integer,String> spinnerMap = new HashMap<Integer, String>();
for (int i = 0; i < Province_ID.size(); i++)
{
   spinnerMap.put(i,Province_ID.get(i));
   spinnerArray[i] = Province_NAME.get(i);
}

设置Spinner的值

ArrayAdapter<String> adapter =new ArrayAdapter<String>(context,android.R.layout.simple_spinner_item, spinnerArray);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);

获取 spinner 的值

String name = spinner.getSelectedItem().toString();
String id = spinnerMap.get(spinner.getSelectedItemPosition());

@HareshChhelana,谢谢您提供的绝佳示例。对于spinnerArray、province_NAME和province_ID,我使用了arraylists,因为它使一些对象处理变得更容易,所以我只需要使用spinnerArray.add(provinceName.get(i)),而不是spinnerArray[i] = ...。这可能有助于解决一些索引越界问题。无论如何,感谢您提供的完美解决方案! - Janpan
@HareshChhelana 我不确定,但是 HashMap 是否保留插入顺序?(我记得 HashMap 存在一些问题,可能导致随机顺序)。 - medskill
@medskill,根据更改,我已将存储索引作为键,将ID作为值,这样可以解决下拉列表项中相同名称的问题。 - Haresh Chhelana
为了保持插入元素的顺序,您应该使用LinkedHashMap。 - Mitro
不需要创建第二个数组spinnerArray,只需使用spinnerMap.values(): - L.Grillo

2

使用LinkedHashMap,将“您希望在下拉列表中显示的字符串”作为键,将基于下拉列表选择要检索的对象作为值进行存储。例如,如果某些原因与下拉列表项相关联的是Float数据类型,请使用以下代码:

LinkedHashMap<String , Float> aMap = new LinkedHashMap<>(10);

对于spinner,我们可以将值设置为:

    ArrayList<String> values = new ArrayList<>(aMap.keySet());
    ArrayAdapter<String> adapter = new ArrayAdapter<String>(getContext(), android.R.layout.simple_spinner_item,values);
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    spinner.setAdapter(adapter);

最后,在OnItemSelectedListener中检索浮点值,如下所示:

 @Override
 public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
                aMap.get(adapterView.getItemAtPosition(i));
                
            }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接