ViewPager2中ViewHolder不可见时如何重置其视图状态
问题解答
1. 能否在页面切换回调中直接获取对应位置ViewHolder?
官方提供的ViewPager2.OnPageChangeCallback没有内置获取对应ViewHolder的能力,无法直接从回调参数中拿到实例。
2. 如何根据position获取对应ViewHolder实例?
ViewPager2内部是基于RecyclerView实现的,你可以先拿到内部封装的RecyclerView实例,再调用RecyclerView的findViewHolderForAdapterPosition()方法获取对应位置的ViewHolder,示例代码如下:
private var lastPosition = -1 private var callback = object: ViewPager2.OnPageChangeCallback() { override fun onPageSelected(position: Int) { if (lastPosition >= 0) { // 获取ViewPager2内部的RecyclerView val recyclerView = viewpager.getChildAt(0) as RecyclerView // 查找lastPosition对应的ViewHolder,注意要做类型安全转换和判空 val lastHolder = recyclerView.findViewHolderForAdapterPosition(lastPosition) as? MyViewHolder lastHolder?.resetScrollState() } lastPosition = position } }
注意:如果对应位置的页面已经被回收,该方法会返回null,此时无法执行重置逻辑,可能出现遗漏。
3. 更优的处理方案
不需要在Fragment中注册页面切换监听,直接在你的ListAdapter子类中重写两个生命周期回调方法即可,逻辑完全内聚在Adapter中,不会出现遗漏:
class YourPagerAdapter : ListAdapter<你的数据类型, 你的ViewHolder类型>(DIFF_CALLBACK) { // 省略你原有实现的onCreateViewHolder、onBindViewHolder逻辑 // 页面滑走不可见、ItemView从窗口 detach 时触发 override fun onViewDetachedFromWindow(holder: 你的ViewHolder类型) { super.onViewDetachedFromWindow(holder) holder.resetScrollState() } // ViewHolder被系统回收时触发,做兜底重置 override fun onViewRecycled(holder: 你的ViewHolder类型) { super.onViewRecycled(holder) holder.resetScrollState() } }
这个方案不需要额外存储ViewHolder实例,也不需要处理页面位置的记录逻辑,同时覆盖了页面临时滑走和永久回收两种场景,完全避免ViewHolder复用导致的滚动状态错乱问题。
内容的提问来源于stack exchange,提问作者RedGlyph
相关产品推荐
相关产品推荐

