ViewPager2滑动后未重建UI导致未点击按钮颜色异常变更问题
问题根因
ViewPager2底层基于RecyclerView实现,自带ViewHolder复用机制。你点击某个页面的按钮修改颜色后,被修改过样式的ViewHolder滑动到离屏位置时,会被复用给新滑入的页面;而你在bind方法中没有主动重置按钮的默认背景色,就会出现未点击按钮也变色的问题,并非UI未重建,恰恰是复用了旧UI实例导致的。
修复方案
核心逻辑是单独存储按钮选中状态,每次绑定数据时强制重置UI样式,避免复用带来的样式残留,修改后的适配器代码如下:
class MyAdapter(private val mData :List<String>) : RecyclerView.Adapter<MyAdapter.MyViewHolder>() { // 存储每个位置按钮的选中状态,默认全部未选中 private val selectStatus = BooleanArray(mData.size) { false } inner class MyViewHolder(private val binding:ItemDataBinding) :RecyclerView.ViewHolder(binding.root) { fun bind(data :String, position: Int) { binding.mText.text = data // 每次绑定数据时显式设置按钮背景,不要依赖默认值 if (selectStatus[position]) { binding.btnclick.setBackgroundColor(ContextCompat.getColor(binding.root.context, R.color.blue)) } else { // 替换为你的按钮默认背景色 binding.btnclick.setBackgroundColor(ContextCompat.getColor(binding.root.context, R.color.your_default_btn_color)) } // 点击事件修改状态后刷新当前条目 binding.btnclick.setOnClickListener { selectStatus[position] = true notifyItemChanged(position) } } } override fun onBindViewHolder(holder: MyViewHolder, position: Int) { holder.bind(mData[position], position) } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder { val binding = ItemDataBinding.inflate(LayoutInflater.from(parent.context),parent,false) return MyViewHolder(binding) } override fun getItemCount(): Int { return mData.size } }
可选优化
如果不需要持久保留按钮的选中状态,滑动离开页面后就重置颜色,不需要额外存储状态,直接在bind方法开头强制重置按钮为默认背景色即可:
fun bind(data :String) { // 开头先重置样式,避免复用残留 binding.btnclick.setBackgroundColor(ContextCompat.getColor(binding.root.context, R.color.your_default_btn_color)) binding.mText.text = data binding.btnclick.setOnClickListener { binding.btnclick.setBackgroundColor(ContextCompat.getColor(binding.root.context,R.color.blue)) } }
这种方案实现更简单,但滑动回之前点击过的页面时,按钮选中状态会消失,可根据业务需求选择。
内容的提问来源于stack exchange,提问作者Abdulsamet Kılınçarslan
相关产品推荐
相关产品推荐

