如何从多选列表视图中获取所选项目

51

我正在使用一个数组适配器,并向其中添加一个字符串数组列表,该列表是多选的。如何获取所单击的列表项的值?

my_contacts_list.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
ArrayAdapter<String> adapter=new ArrayAdapter<String>(this, android.R.layout.simple_list_item_multiple_choice,conts_list);
  my_contacts_list.setAdapter(adapter);
我正在尝试做这件事,
SparseBooleanArray positions = my_contacts_list.getCheckedItemPositions();
  int size=positions.size();
  int i=0;
  while(i <= size){
   conts_list.get(positions.get(i));
   i++;
  }

但是position.get(i)是一个数组列表,那么如何检索选定的项目呢?


你正在使用MultiAutoCompleteTextView吗? - GSree
@preethi看一下这个答案,可能有帮助:https://dev59.com/wXbZa4cB1Zd3GeqPBhOd#20171191 - Chanakya Vadla
13个回答

48

SparseBooleanArray.get方法返回一个布尔值,但我认为你需要对列表中的每个位置进行检查,例如:

int len = listView.getCount();
SparseBooleanArray checked = listView.getCheckedItemPositions();
for (int i = 0; i < len; i++)
 if (checked.get(i)) {
  String item = cont_list.get(i);
  /* do whatever you want with the checked item */
 }

这个答案是错误的,你有尝试过吗?还是只是对我来说是错的?在我的情况下,我只得到了12个结果,前七个是正确的,其余的是错误的,我的多选列表中总共有42个项目,稀疏布尔键指向我的列表索引,请修正你的答案,因为它被标记为正确的答案,我不希望有人因为跟随了错误的答案而失败,让 Stack Overflow 保持干净;) - Shereef Marzouk
2
我认为这个例子中的关键是要知道cont_list是您提供给适配器的原始列表。鉴于此,我不确定您如何使其无法工作。如果索引i在传递给适配器的原始列表项中被选中,则checked.get(i)将仅返回TRUE。 - Todd Painton
简短而有用的回答,谢谢。 - Ronak Mehta
谢谢,它完美地工作了,我们不需要删除未选中的项目。for循环会自动为我们完成这个任务。 - Arpit Patel

46

这个API很混乱,以下是适用于我的方法。

SparseBooleanArray checked = tags.getCheckedItemPositions();
for (int i = 0; i < checked.size(); i++) {
    if(checked.valueAt(i)) {
        Tag tag = (Tag) tags.getItemAtPosition(checked.keyAt(i));
        Log.i("xxxx", i + " " + tag);
    }
}

那对我不起作用。Daren的解决方案对我有用。 - Cheok Yan Cheng
如何在单击项视图元素时仅选择该项而不是所有项?就像在Solid Explorer中一样。 - DavyJonesUA
1
对我来说,checked.size() 总是返回 0,并且这些值似乎在一开始就达到了 12,但是具有正确的键/值对。因此,我只需使用 ListView 的 getCount 来获取迭代的限制,并在遇到 IndexOutOfBoudsException 时结束。虽然很丑陋,但目前为止它可以工作。 - sebastianf182
返回列表中已选项目的集合。仅当选择模式未设置为CHOICE_MODE_NONE时,结果才有效。 - Jijo Thomas
这是一个不清晰的答案。别误会,我指的是编程语言的语法。 - Ali.Rashidi

17

我认为从这个SparseArray中获取信息的最快方法是遍历键(实际上我相当确定上面的解决方案在所有情况下都不会起作用)。对于每个选定的索引,ListView将在SparseBooleanArray中输入一对(索引,true)。

因此,代码可能看起来像这样:

SparseBooleanArray checked = lv.getCheckedItemPositions();
int size = checked.size(); // number of name-value pairs in the array
for (int i = 0; i < size; i++) {
    int key = checked.keyAt(i);
    boolean value = checked.get(key);
    if (value)
        doSomethingWithSelectedIndex(key);
}

1
对我来说没问题。这种编码方式比其他方式更易读。 - Cheok Yan Cheng

4
我认为Daren Robbins的答案是错误的,以下是我的答案:
ArrayList<String> ids = extras.getStringArrayList("commonids");
SparseBooleanArray checked = lv.getCheckedItemPositions();
for (int i = 0; i < checked.size(); i++) {
    if(checked.get(i))
        Log.i("CheckedItem", ids.get(checked.indexOfKey(i)));
}

假设ids是一个ArrayList,其大小与ListView相同,其中包含了ListView中项目的ID。

3

像许多其他事情一样,在Android中,多选 ListView 是一个真正的问题。

与其仅仅请求所选项目作为Object列表(亲爱的Google,这是我们期望的):

List selected_items = my_list_view.getSelectedItems();

我们被迫使用这个极其荒谬的API:

SparseBooleanArray checked = my_list_view.getCheckedItemPositions();
    int num_selected = 0;
    for(int i = 0; i < checked.size(); i++) {
        if(checked.valueAt(i)) {
            num_selected++;
            int key = checked.keyAt(i);
            boolean value = checked.get(key);
            if (value) {
                //
            }
        }
    }

那个名字极差的SparseBooleanArray通过在ListView上调用更为糟糕的getCheckedItemPositions()来填充。但是,它返回的不是列表中每个选定/选中项的位置,而是列表中曾经被触摸过无论其是否当前实际选定的每个项目的位置!难以置信,但却是真实的。
为了计算项目是否当前实际选中,我们被迫在循环遍历“曾经被触摸”的项目的数组时测试valueAt(i)的真实性。
除了这种疯狂之外,如果我们想计算所选项目的数量,似乎我们被迫自己递增计数器(例如num_selected)。
有了这样的API,开发人员变得愤怒也就不足为奇了!

3
事实上,您需要迭代所有列表视图项目而不是已检查的位置。
定义变量:
  • listView (The instance of you ListView)
  • names (the ArrayList you are )
  • saveCheckedName (save all checked name to this Arraylist)

     SparseBooleanArray checkedPositions = listView.getCheckedItemPositions();
        for (int i = 0; i < subjectListView.getCount(); i++) {
                        if (checkedPositions.get(i) == true) {
                            saveCheckedName.add(names.get(i));
                        }
                    }
    

1

提供信息,以下是谷歌的做法:

摘自 http://mytracks.googlecode.com/hg/MyTracks/src/com/google/android/apps/mytracks/util/Api11Adapter.java

/**
* Gets the checked positions in a list view.
* 
* @param list the list view
*/
private int[] getCheckedPositions(ListView list) {
    SparseBooleanArray positions  = list.getCheckedItemPositions();
    ArrayList<Integer> arrayList = new ArrayList<Integer>();
    for (int i = 0; i < positions.size(); i++) {
        int key = positions.keyAt(i);
        if (positions.valueAt(i)) {
            arrayList.add(key);
        }
    }
    int[] result = new int[arrayList.size()];
    for (int i = 0; i < arrayList.size(); i++) {
        result[i] = arrayList.get(i);
    }
    return result;
}

这里是我改编后的版本:

public static List<Integer> getAbsListViewCheckedItemPositions(AbsListView absListView) {
    SparseBooleanArray checked  = absListView.getCheckedItemPositions();
    List<Integer> positions = new ArrayList<>();
    int checkedSize = checked.size();
    for (int i = 0; i < checkedSize; i++) {
        if (checked.valueAt(i)) {
            positions.add(checked.keyAt(i));
        }
    }
    return positions;
}

1
非常简单,使用以下代码。
listViewRequests.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                    AppCompatCheckedTextView checkBox = (AppCompatCheckedTextView) view;

                    if (checkBox.isChecked() == true){
                        Log.i("CHECK",checkBox.isChecked()+""+checkBox.getText().toString());
                    }
                }
            });

兄弟,那确实是个不错的答案。我在Xamarin.Android中使用了这种技术。 - Ishwor Khanal

1
我们在Android实用类中使用这个。泛型有助于防止编译器警告,但如果您的适配器返回多种类型,您可以删除它们。
public static <T> Collection<T> getCheckedItems(ListView listView) {
        Collection<T> ret = new ArrayList();
        SparseBooleanArray checkedItemPositions = listView.getCheckedItemPositions();
        for (int i = 0; i < checkedItemPositions.size(); i++) {
            if (checkedItemPositions.valueAt(i)) {
                T item = (T) listView.getAdapter().getItem(checkedItemPositions.keyAt(i));
                ret.add(item);
            }
        }
        return ret;
}

1
如何使用第二个ArrayList解决问题:
  1. 创建了第二个ArrayList实例
  2. 更新了该ArrayList实例中的UNCHECKED项目
  3. 将其添加到我的listadapter中

    public void removeSelectedItems(){
    
    updatedList = new ArrayList<String>(); //初始化第二个ArrayList
    
    int count = lv.getCount();  //我的ListView项目数
    SparseBooleanArray checkedItemPositions = getListView().getCheckedItemPositions();
    for (int i=0;i < count;i++){
        if(!checkedItemPositions.get(i))
    
        updatedList.add(liveNames.get(i)); //liveNames是当前的ArrayList     
        Log.e("TEST", liveNames.get(i));
    }
    
    adapter = new ArrayAdapter<String>(this,
            android.R.layout.simple_list_item_multiple_choice, updatedList);
    
    setListAdapter(adapter);}
    
希望它有所帮助 :)

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