You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

RecyclerView垂直滚动时主适配器项水平滚动位置混乱问题咨询

解决RecyclerView垂直滚动时子项水平滚动位置错乱的问题

嘿,这个问题我太熟了——这完全是RecyclerView的ViewHolder复用机制搞的鬼!当垂直RecyclerView滚动时,滑出屏幕的ViewHolder会被回收复用给新进入屏幕的项,如果没给每个子项的水平滚动位置做持久化和恢复,就会出现位置“串台”的情况。

核心解决方案:给每个数据项绑定滚动位置,在绑定ViewHolder时恢复

我给你分步骤拆解:

  1. 在数据模型中添加滚动位置字段
    首先,在你的列表数据类(比如Channel)里加一个字段,用来存储对应子项的水平滚动X坐标:

    public class Channel {
        // 其他原有字段...
        private int horizontalScrollX;
    
        public int getHorizontalScrollX() {
            return horizontalScrollX;
        }
    
        public void setHorizontalScrollX(int horizontalScrollX) {
            this.horizontalScrollX = horizontalScrollX;
        }
    }
    
  2. 给水平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);
                    }
                }
            });
        }
    }
    
  3. 在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 12:00:16