【问题标题】:Android - setChoiceMode on custom ListView = no effectAndroid - 自定义 ListView 上的 setChoiceMode = 无效
【发布时间】:2012-12-20 08:57:40
【问题描述】:

我正在使用用于我的 ListView 的自定义适配器。创建 ArrayList 后

WifiListAdapter<WifiListItem> adapter = new WifiListAdapter<WifiListItem>(
            this, R.layout.listview_item_text, listItems);

我的应用中有以下代码:

    ListView listView = (ListView) findViewById(android.R.id.list);
    listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
    listView.setAdapter(adapter);

但是,当我尝试单击复选框时,没有任何反应。所以我必须手动管理切换复选框状态。

    protected void onListItemClick(ListView l, View v, int position, long id) {
    CheckedTextView checkBox = (CheckedTextView) v
            .findViewById(R.id.text1);
    if (checkBox != null) {
        checkBox.toggle();

然后就可以了。 (在此之前我必须删除 setChoiceMode 方法调用)

那么可能是什么问题?为什么没有效果?

我的 R.layout.listview_item_text.xml

    <TextView
    android:id="@+id/topText"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textSize="22sp"
    android:paddingTop="7dp"
    android:textColor="?android:attr/textColorPrimary"/>

<TextView
    android:id="@+id/botText"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textSize="17sp"
    android:paddingTop="2dp"
    android:paddingBottom="7dp"
    android:textColor="?android:attr/textColorTertiary"
 />

在我的适配器中,我使用以下代码填充复选框布局:

                convertView = mInflater.inflate(
                        R.layout.listview_item_checkbox, null);

            CheckedTextView checkbox = ((CheckedTextView) convertView
                    .findViewById(R.id.text1))

listview_item_checkbox.xml

    <CheckedTextView
    android:id="@+id/text1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center_vertical"
    android:textSize="22sp"
    android:paddingTop="7dp"
    android:paddingBottom="7dp"
    android:checkMark="?android:attr/listChoiceIndicatorMultiple"
     />

【问题讨论】:

  • 我猜这是你的布局中的一些东西(R.layout.listview_item_text)。可以发一下吗?
  • 这是因为您正在创建自己的适配器“WifiListAdapter”,而不是使用标准的 ArrayAdapter。
  • 你能发布你的 text1.xml 吗?而且您不需要此代码 - if (checkBox != null) checkBox.toggle();
  • 查看这个question的答案
  • @Mohamed_AbdAllah 我并没有真正理解。这是否意味着现在可以在自定义 Adapter 上调用此方法?

标签: android android-layout android-listview


【解决方案1】:

代替你的代码:

if (checkBox != null)
        checkBox.toggle();

试试这样的:

if (checkBox != null) checkBox.setChecked(l.getCheckedItemPositions().get(position));

如果可以 - 改进您的代码(创建 CheckableFrameLayout 作为列表项的父布局)。 ListView 保留BooleanSparseArray 的已检查位置(您可以使用方法getCheckedItemPositions() 获取)。在代码 (grepcode) 中,仅当 View 正在实现 Checkable 时,它才会自行设置 View。如果创建 CheckableFrameLayout 并作为主父节点,则不必在适配器中处理这些情况。

【讨论】:

  • 抱歉,我还是不太明白。 CheckedTextView 正在实现 Checkable。我知道AbsListView 一直在跟踪mCheckStates 成员变量中复选框的状态。问题是如果列表中的那个项目正在实现Checkable,为什么它不能正确处理它?
  • 对不起,我可能误会了。如果您只是删除这部分代码怎么办:if (checkBox != null) checkBox.toggle();,因为当您在onListItemClick() 中使用方法toggle() 时,您将取消选中刚刚选中的项目。
  • 谢谢。我终于明白了。我将 LinearLayout 作为我的复选框的父视图。因此,它没有实施 Checkable。 p.s.我现在的代码如下:protected void onListItemClick(ListView l, View v, int position, long id) { final int finalPosition = position; if (v instanceof CheckedTextView) { CheckedTextView checkBox = (CheckedTextView) v;
【解决方案2】:

我相信您必须使用实现Checkable 的小部件。试试android.R.layout.simple_list_item_multiple_choice。如果您需要两行代码,请实现类似的东西。

【讨论】:

  • 您不能扩充您的文本视图并将其转换为CheckedTextView。我猜WifiListAdpapter 是你自己的班级。我不知道您对参数做了什么,但据我所知,您的 getView() 方法必须返回实现 Checkable 的对象才能进行多项选择。否则你必须自己管理检查状态。
  • 我的ListView 中有不同的视图(项目列表)。所以,我正在检查( != null ),所以如果单击了复选框。你是说getView() 方法返回的所有对象都必须实现 Checkable 以便多选有效?
  • 好的。所以我正在这样做。我没有将文本视图转换为 CheckedTextView。我的列表中有复选框。在问题中添加了复选框 xml。
  • 布局中只有一个可检查项是不够的。布局中的顶级小部件必须是可检查的。看看这个:androidxref.com/4.2_r1/xref/frameworks/base/core/java/android/…
  • 但我的顶部小部件是可检查的。我应该在哪里查看 android ListView 源代码?我什至试图删除除 Checkable 之外的所有项目,但仍然没有结果
【解决方案3】:

问题是源代码中存在一些问题(我写这个答案时最新版本的事件,4.3r2.1)。问题来了:

1899        if (mChoiceMode != CHOICE_MODE_NONE && mCheckStates != null) {
1900            if (child instanceof Checkable) {
1901                ((Checkable) child).setChecked(mCheckStates.get(position));
1902            } else if (getContext().getApplicationInfo().targetSdkVersion
1903                    >= android.os.Build.VERSION_CODES.HONEYCOMB) {
1904                child.setActivated(mCheckStates.get(position));
1905            }
1906        }

源代码: http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.3_r2.1/android/widget/ListView.java?av=f

如果您的 minSDK 是 11,那么对您的问题最简单的答案是自定义复选框,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<selector
 xmlns:android="http://schemas.android.com/apk/res/android" >
 <item android:state_activated="true" android:drawable="@drawable/checkbox_selected"/>
 <item android:state_activated="false" android:drawable="@drawable/checkbox_deselected" />
 <item android:state_checked="false" android:drawable="@drawable/checkbox_deselected" />
 <item android:state_checked="true" android:drawable="@drawable/checkbox_selected" />
</selector>

将其作为xml文件保存到drawable文件夹中并作为布局引用。

中层解决方案设置在ItemClickListener上,根据选择模式执行不同的行为。

以下是有效的源代码: https://github.com/jiahaoliuliu/CustomizedListRow

MarvinLab 提供了一个困难但正确的解决方案,您可以在这里找到它: http://www.marvinlabs.com/2010/10/29/custom-listview-ability-check-items/

相关问题: What is the difference between the states selected, checked and activated in Android?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-01
    • 2011-09-12
    • 1970-01-01
    • 2015-03-28
    • 2015-06-23
    • 1970-01-01
    • 2013-12-23
    相关资源
    最近更新 更多