如何实现横向Recyclerview无限滚动,滚动到末尾无需回跳至首个item
RecyclerView无限轮播平滑衔接实现方案
核心实现思路是通过伪无限长度的方式模拟循环效果,避免滚动到边界时的回跳动效:
- 改造Adapter返回超大的item总数,用取模的方式复用真实数据源
- 移除原有边界判断逻辑,直接持续向后滚动即可
步骤1:修改AdsParseAdapter逻辑
public class AdsParseAdapter extends RecyclerView.Adapter<AdsParseAdapter.ViewHolder> { private List<AdsParseItem> mDataList; private Context mContext; public AdsParseAdapter(List<AdsParseItem> dataList, Context context) { this.mDataList = dataList; this.mContext = context; } @Override public int getItemCount() { // 返回极大值模拟无限长度 return mDataList == null ? 0 : Integer.MAX_VALUE; } @Override public void onBindViewHolder(@NonNull ViewHolder holder, int position) { // 取模获得真实数据源索引,复用数据 int realIndex = position % mDataList.size(); AdsParseItem realItem = mDataList.get(realIndex); // 原有绑定逻辑保持不变,使用realIndex对应的数据即可 } // 其余ViewHolder创建、条目点击等原有逻辑全部保持不变 }
步骤2:修改setAdsRecyclerView初始化逻辑
private void setAdsRecyclerView() { layoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false) { @Override public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) { LinearSmoothScroller smoothScroller = new LinearSmoothScroller(getContext()) { private static final float SPEED = 300f;// 滚动速度可自行调整 @Override protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) { return SPEED / displayMetrics.densityDpi; } }; smoothScroller.setTargetPosition(position); startSmoothScroll(smoothScroller); } }; adsRecyclerview.setHasFixedSize(true); adsRecyclerview.setLayoutManager(layoutManager); adsRecyclerview.setNestedScrollingEnabled(false); adsParseAdapter = new AdsParseAdapter(adsParseItems, getContext()); adsRecyclerview.setAdapter(adsParseAdapter); LinearSnapHelper linearSnapHelper = new LinearSnapHelper(); linearSnapHelper.attachToRecyclerView(adsRecyclerview); // 新增:初始滚动到中间位置,避免滑动到列表边界 if (adsParseItems != null && adsParseItems.size() > 0) { int initPosition = adsParseItems.size() * 1000; adsRecyclerview.scrollToPosition(initPosition); } Timer timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { // 切到主线程操作避免线程异常 getActivity().runOnUiThread(() -> { // 移除原有边界判断,直接滚动到下一个位置即可 int lastVisiblePos = layoutManager.findLastCompletelyVisibleItemPosition(); layoutManager.smoothScrollToPosition(adsRecyclerview, new RecyclerView.State(), lastVisiblePos + 1); }); } }, 5000, 4000); }
注意事项
- 该方案完全兼容原有SnapHelper的对齐效果,手动滑动也可以正常循环
- Integer.MAX_VALUE约为21亿,按4秒滚动一次计算,完全覆盖普通应用的生命周期,不会出现滑到边界的情况
- 如果后续需要更新轮播数据源,更新后记得重新调用
scrollToPosition设置初始中间位置,再刷新Adapter
内容的提问来源于stack exchange,提问作者crixus
相关产品推荐
相关产品推荐

