RecyclerView垂直滚动时主适配器项水平滚动位置混乱问题咨询
解决RecyclerView垂直滚动时子项水平滚动位置错乱的问题
嘿,这个问题我太熟了——这完全是RecyclerView的ViewHolder复用机制搞的鬼!当垂直RecyclerView滚动时,滑出屏幕的ViewHolder会被回收复用给新进入屏幕的项,如果没给每个子项的水平滚动位置做持久化和恢复,就会出现位置“串台”的情况。
核心解决方案:给每个数据项绑定滚动位置,在绑定ViewHolder时恢复
我给你分步骤拆解:
在数据模型中添加滚动位置字段
首先,在你的列表数据类(比如Channel)里加一个字段,用来存储对应子项的水平滚动X坐标:public class Channel { // 其他原有字段... private int horizontalScrollX; public int getHorizontalScrollX() { return horizontalScrollX; } public void setHorizontalScrollX(int horizontalScrollX) { this.horizontalScrollX = horizontalScrollX; } }给水平RecyclerView添加滚动监听,实时保存位置
在你的Item Holder里,给水平方向的programView(子项里的RecyclerView)设置滚动监听,每次滚动时把当前位置存到对应的数据项里:// 这是AdapterChanels的ViewHolder内部代码 public class ViewHolder extends RecyclerView.ViewHolder { RecyclerView programView; public ViewHolder(View itemView) { super(itemView); programView = itemView.findViewById(R.id.program_view); // 设置滚动监听 programView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); // 获取当前水平滚动的X位置 int currentScrollX = recyclerView.getScrollX(); // 获取当前ViewHolder对应的列表位置 int adapterPosition = getAdapterPosition(); // 确保位置有效,避免越界 if (adapterPosition != RecyclerView.NO_POSITION) { // 保存到对应的数据项里 adapterChanels.getDataList().get(adapterPosition).setHorizontalScrollX(currentScrollX); } } }); } }在onBindViewHolder中恢复滚动位置
这是最关键的一步!每次绑定ViewHolder的时候,把之前保存的滚动位置恢复回去:@Override public void onBindViewHolder(@NonNull ViewHolder holder, int position) { Channel currentItem = dataList.get(position); // 其他绑定逻辑(比如设置标题、加载子项数据等)... // 恢复水平滚动位置 holder.programView.scrollTo(currentItem.getHorizontalScrollX(), 0); }
额外注意事项
- 如果你用的是
LinearLayoutManager,也可以用scrollToPositionWithOffset来更精准控制,但scrollTo已经能解决大部分场景 - 务必确保
getAdapterPosition()返回的不是RecyclerView.NO_POSITION,避免空指针或者数组越界 - 如果你的数据列表有刷新(比如下拉刷新、加载更多),要保证滚动位置的字段能正确保留或初始化
内容的提问来源于stack exchange,提问作者abrutsze
相关产品推荐
相关产品推荐

