【问题标题】:Checkbox becoming 'sticky' in RecyclerView复选框在 RecyclerView 中变得“粘性”
【发布时间】:2017-11-20 16:31:52
【问题描述】:

我有一个对话框,它通过带有复选框的列表接收用户输入,其布局为RecyclerView。但是当我在列表中选择CheckBox 时,列表中更靠后的另一个CheckBox 也会被选中,但我没有这样做。这些图片将有助于说明我的观点。

在这里,我只选择了日历和相机:

但在列表的更下方,Google 和地图也被选中,而我没有选择。

bindActivity 我的代码是:

public void bindActivity(ResolveInfo resolveInfo)
        {
            mResolveInfo = resolveInfo;
            PackageManager pm = getActivity().getPackageManager();
            String appName = mResolveInfo.loadLabel(pm).toString();
            mAppImageView.setImageDrawable(resolveInfo.loadIcon(pm));
            mAppTextView.setText(appName);
        }

如果我在bindActivity 中添加mAppCheckBox.setChecked(false),那么当我在列表中进一步向下并且RecyclerView '循环'列表,然后我向上时,我之前的选择将变为未选中。

我希望有任何关于如何摆脱“粘性”复选框的建议。

【问题讨论】:

  • 您是否尝试过在您的构建器上使用setMultiChoiceItems
  • 使用 CharSequence 并且我正在使用 ResolveInfo 列表填充对话框。我想继续使用它,因为这样我还可以在应用名称旁边显示图标
  • 我也想知道为什么我的问题被否决了。我是新来的,想知道我做错了什么。
  • 天哪,我刚刚读到什么是赏金。谢谢你做这个前辈。
  • 这是因为视图在列表视图中被回收。请阅读:stackoverflow.com/questions/10895763/…stackoverflow.com/questions/5438375/…。它将帮助您了解问题以及解决方案

标签: java android checkbox dialog android-recyclerview


【解决方案1】:

a) 绑定视图时,您似乎没有设置复选框的选中状态。跟踪已选择的项目,然后在进行视图绑定时设置为选中状态。

b) 我不太确定您的意思,但据我所知,the dialog documenation 可能是您与家长交流时所寻找的。​​p>

【讨论】:

  • 我的意思是(b)是我不能通过传统的for 循环输入,因为我不知道列表会有多少项目。如果“增强的for”循环是可行的,那么我将如何在这里使用它?
  • 仍然没有完全跟随。当一个复选框被选中时,或者以您在单击​​列表项时的方式,在该项目上到适配器中的一个单独的列表实例。然后,当您单击对话框中的肯定按钮时,您可以在该列表中执行您希望执行的任何操作(例如,使用我提供的文档中描述的侦听器模式将其传递回活动)。
  • 在遵循您对 (a) 的建议后,我将更新我的问题。我想我可以更具体地向您解释我的第二个问题是什么。
  • 我找到了 (b) 的解决方案,但 (a) 仍然存在。我已经编辑了整个问题以反映我的问题。
  • @SamyakChaudhary,您是否尝试过我在答案中所说的内容?不要只是将其设置为 false,跟踪列表中哪些项目已被选中,然后根据列表是否包含该项目 id 来设置复选框的检查值。
【解决方案2】:

您会看到这种行为,因为 ViewHolders 正在被重用。向下滚动后,上方项目(现在不可见)的ViewHolder 将被重新用于将要显示的新项目。这个ViewHolder 有一个CheckBox,之前已检查过,但没有人明确表示应该取消选中。

您应该注意正确重置状态。您可以将选中的项目位置保存在数组中,然后在onBindViewHolder() 中适当地设置CheckBox 的选定状态:

public class MyAdapter extends RecyclerView.Adapter<Item> {

  final boolean[] checkedArr;

  public MyAdapter(List<Item> list) {
    checkedArr = new boolean[list.size()];
    // Filling all the items as unchecked by default
    Arrays.fill(checkedArr, false);
  }

  @Override public void onBindViewHolder(Item holder, int position) {
    // You have removed the listener in `onViewRecycled`
    // Thus, this `setChecked()` won't cause any listener to be fired
    holder.checkbox.setChecked(checkedArr[holder.getAdapterPosition()]);
    holder.checkbox.setOnCheckedChangeListener(
        (buttonView, isChecked) -> {
          // Retaining checked state in the array
          checkedArr[holder.getAdapterPosition()] = isChecked;
        });
  }

  @Override public void onViewRecycled(Item holder) {
    super.onViewRecycled(holder);
    // When view is being recycled remove the listener
    holder.checkbox.setOnCheckedChangeListener(null);
  }
  ...
}

或者您可以避免“重新发明轮子”,并使用MultiViewAdaptercheckboxes feature 一起提供:单一、单一或无、多种模式。

【讨论】:

  • 它确实有效,但现在我如何检查应用程序的名称?早些时候,我曾经在我的活动持有者中调用setOnCheckedChangeListener,并将ResolveInfo 值传递给另一个List&lt;ResolveInfo&gt; 并从那里开始工作。但是现在监听器不会因此而被触发。
  • 通过循环checkedArr。如果checkedArr[i] == true,那么tempCollection.add(list.get(i));。最后,当循环结束时,返回tempCollection,它将包含所有检查的应用程序。
  • 谢谢伙计。另外,我将如何减去两个列表?在这里,我有一个列表mAllApps,它通过查询PackageManager 和另一个列表'mBlockedApps' 填充,我通过用户输入获得。那么我将如何创建mAllowedApps
  • 没听懂。您也可以创建一个新问题,因为我觉得它与这个问题无关。
  • 使用removeAll?这是 android 参考部分的链接:developer.android.com/reference/java/util/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-24
相关资源
最近更新 更多