RecyclerView多项选择取消选择了错误的ViewHolders

时间:2018-08-07 21:25:56

标签: android android-recyclerview kotlin recycler-adapter

在我的ViewHolder类中,我添加了一个名为isOptionSelected的布尔属性。基本上,此属性的作用是控制是否选择ViewHolder。我做到了,默认情况下所有选项都被选中。

在我的OnBindViewHolder()方法中,我有一个onClickListener()用于ViewHolder.itemView(它检测任何点击并调用名为OnItemClick()的接口方法):

   override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        // Set the text for the itemOption
        val optionString = itemOptions[position]
        holder.itemOption.text = optionString

        // Set the click listener on the view of the holder and send its position
        holder.itemView.setOnClickListener {
            clickListener.onItemClick(position, it)
            notifyDataSetChanged()
        }

        if (holder.isOptionSelected) {
            properties[position] = itemOptions[position]
            holder.itemView.setBackgroundColor(activity.resources.getColor(R.color.popup_window_background))
        } else {
            properties[position] = ""
            holder.itemView.setBackgroundColor(activity.resources.getColor(R.color.icons))
        }
    }

这是我的OnItemClicked界面:

// Interface to use on the main activity to detect clicks
interface OnItemClicked {
    fun onItemClick(position: Int, view: View)
}

这是OnItemClick()上的MainActivity方法:

override fun onItemClick(position: Int, view: View) {
    val vh = menuItemRecyclerView.getChildViewHolder(view) as MeridesAndSaladsAdapter.ViewHolder
    // Invert the boolean value that the vh item holds
    vh.isOptionSelected = !vh.isOptionSelected
}

这是我的ViewHolder班:

class ViewHolder(itemView: View?) : RecyclerView.ViewHolder(itemView) {
    var itemOption: TextView = itemView!!.findViewById(R.id.meridesAndSaladsOption)
    // All options are selected by default
    var isOptionSelected: Boolean = true
}

问题是,当我单击ViewHolder.itemView时,取消选择的视图在我点击的视图上方1-2行。在取消选择某些行然后尝试选择一些取消选择的行之后,这些选择似乎是随机的。而且,有时当我取消选择或选择某些内容时,也会更改一些额外的行。

我缺少什么吗?还是我做错了什么?

2 个答案:

答案 0 :(得分:2)

您的ViewHolders将被重用,并在发生这种情况时将其isOptionsSelected值重置为默认值(True)。您需要存储是否在ViewHolder类之外选择项目,并在onBindViewHolder中获取/加载值,可能将值存储为itemOptions对象的一部分。另外,还需要从onClickListeners中切换这些对象(而不是视图持有者)的值。

答案 1 :(得分:1)

此答案基于您正在做某事的事实,我知道您不应该这样做。解决此问题可能无法解决您的问题,但仍然值得指出:

position的{​​{1}}自变量不应被视为onBindViewHolder()。换句话说,视图持有者的位置可以随时间变化。

您发布的代码包括以下内容:

final

想象一下,您的视图持有者最初是绑定到位置holder.itemView.setOnClickListener { clickListener.onItemClick(position, it) notifyDataSetChanged() } 的,然后在列表的开头插入两行。您的点击监听器仍会呼叫14,但是您的 real 位置现在是onItemClick(14, it)

您可以通过使用16上的getAdapterPosition()方法来解决此问题。这将为您提供实际位置,而不仅仅是初始位置:

ViewHolder

有关更多信息,请参阅以下Google IO演示文稿:https://www.youtube.com/watch?v=LqBlYJTfLP4&feature=youtu.be&t=43m10s(时间戳记为43:10,他们在此谈论此holder.itemView.setOnClickListener { clickListener.onItemClick(holder.getAdapterPosition(), it) notifyDataSetChanged() } 问题)。