如何解决父RecyclerView中子横向RecyclerView notifyItemChanged后跳回顶部问题
解决横向子RecyclerView调用
notifyItemChanged后跳回位置0的问题 核心原因
调用notifyItemChanged时,子RecyclerView会触发视图重新绑定,默认会重置LinearLayoutManager的滚动位置,导致之前的滚动状态丢失。
具体解决方案
保存并恢复滚动位置
在更新子Adapter前,先记录当前滚动的位置和偏移量,更新完成后再恢复:// 获取子RecyclerView的布局管理器 val layoutManager = childRecyclerView.layoutManager as LinearLayoutManager // 记录第一个可见项的位置与偏移量 val firstVisiblePos = layoutManager.findFirstVisibleItemPosition() val offset = layoutManager.findViewByPosition(firstVisiblePos)?.left ?: 0 // 执行条目更新 adapter?.notifyItemChanged(10) // 恢复之前的滚动位置 layoutManager.scrollToPositionWithOffset(firstVisiblePos, offset)优化ViewHolder绑定逻辑
在onBindViewHolder中仅更新数据变化的视图,避免重置RecyclerView的布局参数或重新设置LayoutManager:override fun onBindViewHolder(holder: ChildViewHolder, position: Int) { // 只更新需要变更的内容,比如文本、图片 holder.itemTitle.text = dataList[position].title holder.itemIcon.setImageResource(dataList[position].iconRes) // 禁止在此处重新配置RecyclerView的核心参数 }使用DiffUtil实现精准更新
通过DiffUtil计算新旧数据的差异,只更新真正变化的条目,减少不必要的视图重置:class ChildDataDiffCallback( private val oldList: List<ChildItemModel>, private val newList: List<ChildItemModel> ) : DiffUtil.Callback() { override fun getOldListSize() = oldList.size override fun getNewListSize() = newList.size override fun areItemsTheSame(oldPos: Int, newPos: Int): Boolean { return oldList[oldPos].itemId == newList[newPos].itemId } override fun areContentsTheSame(oldPos: Int, newPos: Int): Boolean { return oldList[oldPos] == newList[newPos] } } // 在子Adapter中调用更新 fun updateItems(newItems: List<ChildItemModel>) { val diffResult = DiffUtil.calculateDiff(ChildDataDiffCallback(currentItems, newItems)) currentItems = newItems diffResult.dispatchUpdatesTo(this) }补充焦点控制
除了已设置的android:descendantFocusability="blocksDescendants",在子RecyclerView的布局中额外添加:android:focusable="false" android:focusableInTouchMode="false"
内容的提问来源于stack exchange,提问作者Suman Radhakrishnan
相关产品推荐
相关产品推荐

