在Android开发中有时候在RecyclerView
中使用Checkbox
进行选中操作:
当我们选中第一个,然后滑动列表发现下面同样有一个也是被选中的,但是其实我们没有去选择,这是因为RecyclerView
的复用item布局导致的。为了解决这个问题,通常会把当前选择的位置存储在一个Boolean
类型的数组中,或者存储在Model
中的一个字段中也是可以的:
// 数据源
private var mList: List<String> = list
// 存储选中的item
private var mEllipsis = hashMapOf<Int, Boolean>()
override fun onCreateViewHolder(p0: ViewGroup, p1: Int): ListAdapter.ListViewHolder {
var view = LayoutInflater.from(p0.context).inflate(R.layout.view_reyclerview_item_layout, p0, false)
return ListAdapter.ListViewHolder(view, itemClick)
}
override fun getItemCount(): Int {
return mList.size
}
override fun onBindViewHolder(holder: ListAdapter.ListViewHolder, position: Int) {
// 判断是否已经选中
holder.itemView.cb_check.isChecked = mEllipsis.containsKey(position)
holder.itemView.cb_check.setOnCheckedChangeListener { buttonView, isChecked ->
// 选中存储,否则删除
if (isChecked) {
mEllipsis[position] = true
} else {
mEllipsis.remove(position)
}
}
}
这样就解决了错乱的问题。但是另一个问题也伴随产生:当我们选择第一个然后滑动底部,再次滑动到顶部的时候发现选中的第一个已经未选中状态了。
debug发现当我们往下滑动一段距离之后Checkbox
的setOnCheckedChangeListener
方法会被调用,然后isChecked = false
,这样就把第一个从数组中删除了,导致回到顶部是未选中的状态。个人觉得是RecyclerView
复用第一个布局的时候,当前的这个item是未选中,然后就直接修改了Checkbox
的选中状态为false
。
解决方案:
第一种:在holder.itemView.cb_check.isChecked = mEllipsis.containsKey(position)
之前先给Checkbox
的setOnCheckedChangeListener
设置为null
。具体代码:
override fun onBindViewHolder(holder: ListAdapter.ListViewHolder, position: Int) {
// 先设置为null
holder.itemView.cb_check.setOnCheckedChangeListener(null)
// 判断是否已经选中
holder.itemView.cb_check.isChecked = mEllipsis.containsKey(position)
holder.itemView.cb_check.setOnCheckedChangeListener { buttonView, isChecked ->
// 选中存储,否则删除
if (isChecked) {
mEllipsis[position] = true
} else {
mEllipsis.remove(position)
}
}
}
第二种:由于往下滑动导致isChecked = false
是系统所为,而非人为点击,所以在Checkbox
的setOnCheckedChangeListener
方法中判断一下是不是点击导致的状态改变,也是可以解决的:
holder.itemView.cb_check.setOnCheckedChangeListener { buttonView, isChecked ->
// 判断是不是人为点击
if (buttonView.isPressed) {
// 选中存储,否则删除
if (isChecked) {
mEllipsis[position] = true
} else {
mEllipsis.remove(position)
}
}
}
第三种:
把Checkbox
的setOnCheckedChangeListener
改为setOnClickListener
:
holder.itemView.cb_check.setOnClickListener {
if (holder.itemView.cb_check.isChecked) {
mEllipsis[position] = true
} else {
mEllipsis.remove(position)
}
}
第四种:
把Checkbox
换成ImageView
:
方法和第三种一样,只不过更换个控件。