为何滚动RecyclerView时LinearLayoutManager.childAt()返回null
问题根因
你踩了RecyclerView最常见的位置概念混淆的坑:getChildAt()的入参根本不是Adapter的item位置。
RecyclerView里存在两套完全独立的位置计数规则:
- 你通过LayoutManager拿到的
firstVisibleItemPosition、lastVisibleItemPosition,是Adapter数据集层面的位置下标,对应你传给Adapter的列表数据的索引,计数范围覆盖整个数据集。 RecyclerView.getChildAt(int index)接收的参数,是当前已经attach到RecyclerView窗口上的子View的布局索引,这个索引永远从0开始计数,只统计当前屏幕上实际挂载的、没有被回收掉的子View,和Adapter位置没有直接绑定关系。
你之前列表在顶部、firstVisibleItemPosition为0时,子View的布局索引刚好和Adapter位置数值完全一致,属于特殊场景下的巧合,让你误以为两个位置是同一个东西,所以当时逻辑看起来正常。
对应你遇到的场景:小幅下滑后,当前屏幕上挂载的子View对应的Adapter位置是4、5、6、7,这四个子View的布局索引实际是:
childAt(0)→ 对应Adapter位置4的itemchildAt(1)→ 对应Adapter位置5的itemchildAt(2)→ 对应Adapter位置6的itemchildAt(3)→ 对应Adapter位置7的item
此时RecyclerView总共只挂载了4个子View,布局索引最大值是3,你直接拿Adapter位置7作为参数传入childAt(),当然会返回null。
正确实现方式
不要直接把Adapter位置传给getChildAt()取View,用LayoutManager提供的专门方法即可:
调用findViewByPosition(adapterPosition),这个方法接收的入参就是Adapter层面的位置,会返回对应位置下当前已挂载到屏幕上的View实例,如果该位置item不在可见区域、已经被回收,才会返回null。
代码示例:
// 先拿到RecyclerView对应的LayoutManager LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager(); // 传入Adapter位置获取对应可见View,比如取位置7的item View targetItemView = layoutManager.findViewByPosition(7);
如果需要遍历当前所有可见item,有两种正确写法:
- 方式1:遍历0到
recyclerView.getChildCount()-1的布局索引拿到所有子View,再通过recyclerView.getChildViewHolder(child).getAdapterPosition()拿到每个子View对应的真实Adapter位置 - 方式2:遍历
firstVisibleItemPosition到lastVisibleItemPosition的Adapter位置区间,逐个调用findViewByPosition()拿到对应View
内容的提问来源于stack exchange,提问作者Tupsi
相关产品推荐
相关产品推荐

