互斥下拉菜单场景下调用notifyDataSetChanged后RecyclerView尺寸不更新问题

预期实现效果
多个下拉菜单实现互斥选择,规则示例如下:
- 可选数组
array = ["A", "B", "C", "D", "E"] - 共3个下拉菜单:menu1、menu2、menu3
- 如果在menu1中选中"A",则menu2和menu3的选项列表中不再展示"A"
问题根因
你打印的dropdownMenu.size调用的是Android View类的size属性,返回的是视图的宽高尺寸,不是RecyclerView的列表项数量,应该取adapter.itemCount获取列表项总数。
除此之外,你的代码还有几处逻辑错误导致RecyclerView不刷新:
1. Adapter的setData方法更新顺序错误
当前你是先清空数据集、调用notify、再添加新数据,顺序不对,应该先更新数据集,再调用刷新通知。
修改ScddAdapter的setData方法:
fun setData(datas: ArrayList<String>) { list.clear() list.addAll(datas) // 数据集更新完成后再发刷新通知 notifyDataSetChanged() }
2. 选中状态没有和Adapter绑定
你之前直接操作RecyclerView的子View修改CheckBox选中状态,没有把选中状态存在Adapter里,RecyclerView刷新的时候状态就会丢失,同时也会导致视图不更新。
首先修改ScddAdapter:
- 新增按值设置选中的方法
- 绑定ViewHolder的时候同步设置CheckBox的选中状态
class ScddAdapter : RecyclerView.Adapter<ScddAdapter.ScddViewHolder>() { // ... 原有代码保持不变 override fun onBindViewHolder(holder: ScddViewHolder, position: Int) { holder.cb.text = list[position] // 绑定的时候同步设置选中状态 holder.cb.isChecked = position == checked holder.itemView.setOnClickListener { holder.cb.isChecked = !holder.cb.isChecked if(holder.cb.isChecked) { checkedStr = holder.cb.text as String checked = holder.layoutPosition } else { checkedStr = "" checked = -1 } this.callback() } } // 新增按值设置选中的方法 fun setCheckedByValue(value: CharSequence) { checkedStr = value checked = if(value.isEmpty()) -1 else list.indexOf(value) notifyDataSetChanged() } // ... 原有代码保持不变 }
然后修改SingleCheckBoxDropDown的setChecked方法,不要直接操作子View,通过Adapter更新状态:
fun setChecked(filter: CharSequence) { adapter.setCheckedByValue(filter) }
3. 单选逻辑冗余
原来的点击事件里遍历RecyclerView子View修改选中状态的逻辑完全不需要,Adapter已经存储了选中位置,刷新后会自动更新所有子项的状态,修改setOnItemClickListenerWithSingleSelect方法:
fun setOnItemClickListenerWithSingleSelect(function: () -> Unit) { adapter.setOnItemClickListener { // 单选逻辑由Adapter的选中状态控制,刷新即可 adapter.notifyDataSetChanged() function() } }
修改完成后,RecyclerView就可以正常刷新,互斥选择逻辑也能正常运行。
内容的提问来源于stack exchange,提问作者Jakkins
相关产品推荐
相关产品推荐

