该应用有一个启用了多项选择的 ListView ,在UI中按预期工作。但是当我使用此代码读取值时:
Log.i(TAG,"Entered SearchActivity.saveCategoryChoice()");
SparseBooleanArray checkedPositions = categorySelector.getCheckedItemPositions();
Log.i(TAG,"checkedPositions: " + checkedPositions.size());
if (checkedPositions != null) {
int count = categoriesAdapter.getCount();
for ( int i=0;i<count;i++) {
Log.i(TAG,"Selected items: " + checkedPositions.get(i));
}
}
无论每个复选框处于什么状态,我都会收到此输出:
Entered SearchActivity.saveCategoryChoice()
checkedPositions: 0
Selected items: false
Selected items: false
Selected items: false
Selected items: false
Selected items: false
Selected items: false
Selected items: false
Selected items: false
Selected items: false
Selected items: false
Selected items: false
Selected items: false
Selected items: false
Selected items: false
Selected items: false
Selected items: false
Selected items: false
SparseBooleanArray似乎对任何不存在的项返回false,因此问题的来源似乎是getCheckedItemPositions()返回一个空数组。该方法的行为就好像ListView中没有项目,但有。
我可以从文档中看到,当ListView没有设置为多选时,没有返回任何值,但是,使用此语句:
categorySelector.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
在我的场景中,我正在使用的适配器是ArrayAdapter的子类,并且(没有任何确凿的证据)我怀疑这可能是原因,但我不明白为什么它不应该工作。
答案 0 :(得分:46)
kcoppock是对的,你需要使用valueAt(),工作代码应该是
SparseBooleanArray checkedItems = categorySelector.getCheckedItemPositions();
if (checkedItems != null) {
for (int i=0; i<checkedItems.size(); i++) {
if (checkedItems.valueAt(i)) {
String item = categorySelector.getAdapter().getItem(
checkedItems.keyAt(i)).toString();
Log.i(TAG,item + " was selected");
}
}
}
答案 1 :(得分:6)
我记得有一段时间我自己遇到了这个问题。 Here是我之前的问题,与您的问题没有直接关系,但包含一些可能有用的代码。您可能想要尝试的是使用checkedPositions.valueAt(int index)
而不是checkedPositions.get(int index)
。我想这可能就是你真正想要的。
答案 2 :(得分:4)
我仍然不知道为什么,但在我的场景中,getCheckedItemPositions()
会返回所有项目的false值。我看不到使用ListView上的方法来获取布尔值的方法。 SparseBooleanArray对象似乎没有真实数据。我怀疑这可能是因为我的实现有些怪癖,也许我已经将ArrayAdapter子类化了。这令人沮丧,像这样的问题是一个真正的时间流失。
无论如何,我使用的解决方案是在创建ListView行时单独为每个Checkbox附加一个处理程序。所以从ListView.getView()
我称这个方法为:
private void addClickHandlerToCheckBox(CheckBox checkbox) {
checkbox.setOnCheckedChangeListener(new OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton arg0, boolean arg1) {
CheckBox checkbox = (CheckBox)arg0;
boolean isChecked = checkbox.isChecked();
// Store the boolean value somewhere durable
}
});
}
答案 3 :(得分:2)
如果您没有选择正确的资源来显示不同的项目,则会发生这种情况。如果您选择内置资源android.R.layout.simple_list_item_multiple_choice,它可以正常工作。方法getCheckedItemPositions
以某种方式耦合到内置资源。
答案 4 :(得分:1)
以上解决方案都不适用于我,而是从ListView获取每个子项(checkedTextView)并查看是否已检查:
ListView myListView = myViewActivity.getListView();
ArrayList<String> selectedChildren2 = new ArrayList<String>();
for(int i = 0;i<myListView.getChildCount();i++)
{
CheckedTextView c = (CheckedTextView) myListView.getChildAt(i);
if(c.isChecked())
{
String child = c.getText().toString();
selectedChildren.add(child);
}
}
答案 5 :(得分:1)
无需处理ListView中项目的检查/取消选中。它已经独自完成了。
似乎没有记录的是ListView只会在以下情况下执行此操作:
ListAdapter
并ListAdapter
使用的ID 稳定。第三点是让我疯狂一段时间的原因。
我不确定'稳定'意味着什么(我想在显示列表时不会改变ID)。
就ListView而言,这意味着hasStableIds()
中的方法ListAdapter
将返回true。
我创建了一个简单的ArrayAdapter
子类,如下所示:
public class StableArrayAdapter<T> extends ArrayAdapter<T> {
public StableArrayAdapter(Context context, int textViewResourceId, List<T> objects) {
super(context, textViewResourceId, objects);
}
@Override
public boolean hasStableIds() {
return true;
}
}
(您已经拥有子类,因此只需添加hasStableIds
覆盖)
当然,需要添加一个与ArrayAdapter
一起使用的构造函数。
将此类用作ListAdapter
后,getCheckedItemPositions()
的行为符合预期。
最后一点:在设置列表适配器后必须调用setChoiceMode
。
答案 6 :(得分:1)
这是一个旧帖子,但由于这在当前谷歌搜索中基本上首先出现,这是了解listView.getCheckedItemPositions()
做什么的快速方法:
除非列表项目没有切换到“#”。在ListView中,它不会被添加到由listView.getCheckedItemPositions()
但是,您真的不希望您的用户点击每个列表项目,以及#34;正确&#34;将它添加到返回的SparseBooleanArray对吧?
因此,您需要结合使用SparseBooleanArray的 valueAt()和 keyAt()。
SparseBooleanArray checkedArray = listView.getCheckedItemPositions();
ArrayList<DataEntry> entries = baseAdapter.getBackingArray(); //point this to the array of your custom adapter
if (checkedArray != null)
{
for(int i = 0; i < checkedArray.size(); i++)
{
if(checkedArray.valueAt(i)) //valueAt() gets the boolean
entries.yourMethodAtIndex(checkedArray.keyAt(i)); //keyAt() gets the key
}
}
答案 7 :(得分:0)
'selected'
和'checked'
之间是否存在相当根本的区别?
怀疑你想setItemChecked()
... {/ p> OnItemSelectedListener
答案 8 :(得分:0)
这个调整为我修好了。 更改getView方法,使“int position”为“final int position”。 然后使用您的复选框执行此操作:
((CheckBox) convertView).setOnCheckedChangeListener(new OnCheckedChangeListener() { public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { list.setItemChecked(position, ((CheckBox) buttonView).isChecked()); } });
让我详细说明一下。 list是对listview的引用,在我的例子中,适配器是持有列表的对话框中的内部类。
答案 9 :(得分:0)
我通过遇到同样的问题找到了这个帖子,但我想我已经找到了一个对我有用的解决方法,原因不明。每当我尝试获取一个值时,我什么都没有,但如果我将列表设置循环设置为false,它就会像预期的那样开始工作。
这实际上是我实现的功能,用户可以选择“全选”或“取消全选”。我在onCreate中运行此方法。
private void selectNone() {
ListView lv = getListView();
for (int i = 0; i < lv.getCount(); i++) {
lv.setItemChecked(i, false);
}
}
现在我所有的价值都是正确的。在我的例子中,获取值只是字符串。
private void importSelected() {
ListView lv = getListView();
SparseBooleanArray selectedItems = lv.getCheckedItemPositions();
for (int i = 0; i < selectedItems.size(); i++) {
if (selectedItems.get(i)) {
String item = lv.getAdapter().getItem(selectedItems.keyAt(i)).toString();
}
}
selectNone(); //Reset
}
我希望这有助于某人。
答案 10 :(得分:0)
我也使用了解决方案gyller建议涉及“启动”listview
ListView lv = getListView();
for (int i = 0; i < lv.getCount(); i++) {
lv.setItemChecked(i, false);
}
在调用getCheckItemPositions()之前,它停止产生错误的结果!
答案 11 :(得分:0)
虽然我不相信我已经尝试过这里描述的每个变体,但这里有一个适合我的变体:)
@Override
public View getView(final int position, View convertView, ViewGroup parent)
{
CheckedTextView retView = (CheckedTextView) convertView;
...
retView.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
CheckedTextView chkVw = (CheckedTextView) v;
// chkVw.toggle();
// chkVw.setChecked(!chkVw.isChecked());
mLstVwWordingSets.setItemChecked(position + 1, !chkVw.isChecked());
}
});
...
}
以后
SparseBooleanArray checkedItemsArray = mLstVwWordingSets.getCheckedItemPositions();
for (int i = 1; i < mLstVwWordingSets.getCount(); i++) //skip the header view
{
if (checkedItemsArray.get(i, false))
Log.d(_TAG, "checked item: " + i);
}
我正在访问位置+ 1,因为我的列表已经到位的标题视图。
HTH
答案 12 :(得分:0)
ArrayList<Integer> ar_CheckedList = new ArrayList<Integer>();
对于我用于将其存储在数组
中的每个复选框holder.chk_Allow.setOnCheckedChangeListener(new OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(isChecked)
ar_CheckedList.add(position);
}
});
点击按钮
for (int i = 0; i < ar_CheckedList.size(); i++)
{
HashMap<String, String> temp=(HashMap<String, String>) contactList.get(ar_CheckedList.get(i));
str_Phone_No=temp.get(TAG_CONTACT_MOBILE);
send(str_Phone_No);
}
答案 13 :(得分:0)
ArrayList<String> selectedChildren = new ArrayList<String>();
for(int i = 0;i<list.getChildCount();i++)
{
CheckBox c = (CheckBox) list.getChildAt(i);
if(c.isChecked())
{
String child = c.getText().toString();
selectedChildren.add(child);
}
}
Log.i(TAG, "onClick: " + selectedChildren.size());
答案 14 :(得分:0)
只需转到定义了listview的xml并设置属性
**android:choiceMode="multipleChoice"**
我的xmlfile
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.ali.myapplication.MainActivity">
<ListView
android:id="@+id/lvCustomList"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:choiceMode="multipleChoice"
/>
</android.support.constraint.ConstraintLayout>
然后在你的javafile中: -
SparseBooleanArray checked=lvDetail.getCheckedItemPositions();
for (int i = 0; i < lvDetail.getAdapter().getCount(); i++) {
if (checked.get(i)) {
Toast.makeText(getApplicationContext(),checked.get(i),Toast.LENGTH_SHORT).show();
}
}