【问题标题】:Unwanted Checkbox selections in RecyclerView in Kotlin (Android)Kotlin (Android) 中 RecyclerView 中不需要的复选框选择
【发布时间】:2018-08-14 19:34:26
【问题描述】:

在我的应用程序中,我有一个 RecyclerView,其中包含 15 个静态项目,包括一个 TextView 和一个 CheckBox:

<android.support.v7.widget.RecyclerView
        android:id="@+id/list"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginBottom="82dp"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        android:scrollbars="vertical" />

点击项目时,相应的复选框被设置为选中,项目被添加到选择列表中。

问题: 当我向下滚动并选择一个项目时,再次向上滚动我总是看到另一个复选框被选中。在调试时我注意到,只有我实际选择的项目被添加到列表中,但是当在 UI 中随机检查/“选择”其他项目时,它仍然是一个糟糕的用户体验。

我怎样才能阻止这种奇怪的行为?

我正在使用视图持有者来管理项目视图:

private inner class MyViewHolder(view: View) : RecyclerView.ViewHolder(view) {
            val checkBox: CheckBox = view.findViewById(R.id.checkbox)
            val text: TextView = view.findViewById(R.id.text)

            init {
                view.setOnClickListener { checkBox.isChecked = !checkBox.isChecked }
                checkBox.setOnCheckedChangeListener { _, isChecked ->
                    val itemText = dataset[adapterPosition]
                    logger.debug("state change $isChecked for $itemText")
                    if (isChecked) selectedItems.add(itemText)
                    else {
                        if (selectedItems.contains(itemText)) selectedItems.remove(itemText)
                    }
                }
            }
        }

我的 onBindViewHolder() 方法包含以下内容:

override fun onBindViewHolder(holder: MyViewHolder?, position: Int) {
            val itemText = dataset[position]
            holder?.text?.text = itemText
        }

【问题讨论】:

  • 这可能是因为 RecylerView 回收逻辑。当您向上滚动时,会在顶部添加一个消失在底部的视图。在您的情况下:选中复选框的视图被回收(绑定)以在另一个位置使用,这不是您想要的。这可以使用 onBindViewHolder 调用修复,并根据每次绑定时的数据状态装饰 UI。介意分享一下你的逻辑吗?
  • @MehmetKologu 是对的。您的“onBindViewHolder”机制应确保为 CheckBox 设置正确的文本和选中状态。如果您可以在那里发布您的实现,那将会很有帮助。另外作为旁注,在您的最后一行检查if (selectedItems.contains(itemText)) 是相当多余的。你可以打电话给selectedItems.remove(itemText)。如果不包含该项目,则没有任何作用。
  • 感谢@Mehmet 的澄清。我将 onBindViewHolder-sn-p 添加到帖子底部
  • 只需在 onBind 方法中添加一行来设置复选框值。这应该如下所示:itemText holder?.checkBox?.setChecked(selectedItems.contains(dataset[‌​position]))。希望这会有所帮助
  • 在您的 onBindViewHolder 中,您将文本设置为正确的文本。您还需要以相同的方式设置复选框的状态。这可能意味着重新考虑您的数据集包含什么,或者通过您的 selectedItems 来决定是否需要检查当前项目的复选框。

标签: android checkbox android-recyclerview kotlin


【解决方案1】:

这可能是由于 RecyclerView 回收逻辑而发生的。当您向上滚动时,会在顶部添加一个消失在底部的视图。在您的情况下:选中复选框的视图被回收(绑定)以在另一个位置使用,这不是您想要的。要解决此问题,您需要跟踪哪些视图应具有选中的复选框。仅根据与该视图关联的数据状态更改视图中复选框的状态。由于您已经在跟踪应该在 selectedItems 数组中检查的项目,只需将以下代码添加到 onBindViewHolder

holder?.checkbox?.isChecked = selectedItems.contains(itemText)

【讨论】:

    【解决方案2】:

    试试这个,这对我有用

    在您的数据模式类中声明一个 boolean 字段以及其他有用的字段

     public boolean isIs_selected() {
            return is_selected;
        }
    
        public void setIs_selected(boolean is_selected) {
            this.is_selected = is_selected;
        }
    
        boolean is_selected = false;
    

    然后在适配器类中执行此操作 在MyViewHolder 类中

    private inner class MyViewHolder(view: View) : RecyclerView.ViewHolder(view) {
    
                init {
                  val checkBox: CheckBox = view.findViewById(R.id.checkbox)
                  val text: TextView = view.findViewById(R.id.text)
                }
            }
    

    然后最后在onBindViewHolder 方法中执行此操作

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {     
                //in some cases, it will prevent unwanted situations
                holder. checkbox!!.setOnCheckedChangeListener(null);
    
                //if true, your checkbox will be selected, else unselected
                holder. checkbox!!.setChecked(array.get(position).isIs_selected());
    
                holder. checkbox!!.setOnCheckedChangeListener { buttonView, isChecked ->
                    dataSet.get(holder.adapterPosition).isIs_selected=isChecked
    
                }
            }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-31
      • 1970-01-01
      • 1970-01-01
      • 2011-09-28
      • 2016-05-29
      相关资源
      最近更新 更多