Android 无限循环RecyclerView的完美实现方案
方案选择
方案1 对Adapter进行修改
网上大部分博客的解决方案都是这种方案,对Adapter做修改。具体如下
首先,让 Adapter 的 getItemCount() 方法返回 Integer.MAX_VALUE,使得position数据达到很大很大;
其次,在 onBindViewHolder() 方法里对position参数取余运算,拿到position对应的真实数据索引,然后对itemView绑定数据
最后,在初始化RecyclerView的时候,让其滑动到指定位置,如 Integer.MAX_VALUE/2,这样就不会滑动到边界了,如果用户一根筋,真的滑动到了边界位置,再加一个判断,如果当前索引是0,就重新动态调整到初始位置
这个方案是挺简单,但并不完美。一是对我们的数据和索引做了计算操作,二是如果滑动到边界,再动态调整到中间,会有一个不明显的卡顿操作,使得滑动不是很顺畅。所以,直接看方案二。
方案2 自定义LayoutManager,修改RecyclerView的布局方式
推荐这个方案。我们都知道,RecyclerView的数据绑定是通过Adapter来处理的,而排版方式以及View的回收控制等,则是通过LayoutManager来实现的,因此我们直接修改itemView的排版方式就可以实现我们的目标,让RecyclerView无限循环。
自定义横向LayoutManager
1.创建自定义LayoutManager
首先,自定义 LooperLayoutManager 继承自 RecyclerView.LayoutManager,然后需要实现抽象方法 generateDefaultLayoutParams(),这个方法的作用是给 itemView 设置默认的LayoutParams,直接返回如下就行。
@Override
public RecyclerView.LayoutParams generateDefaultLayoutParams() {
return new RecyclerView.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
}
2.打开滚动开关
接着,对滚动方向做处理,重写canScrollHorizontally()方法,打开横向滚动开关。注意我们是实现横向无限循环滚动,所以实现此方法,如果要对垂直滚动做处理,则要实现canScrollVertically()方法。
@Override
public boolean canScrollHorizontally() {
return true;
}
3.对RecyclerView进行初始化布局
好了,以上两部是基础工作,接下来,重写 onLayoutChildren() 方法,开始对itemView初始化布局。
@Override
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
if (getItemCount() <= 0) {
return;
}
//preLayout主要支持动画,直接跳过
if (state.isPreLayout()) {
return;
}
//将视图分离放入scrap缓存中,以准备重新对view进行排版
detachAndScrapAttachedViews(recycler);
int autualWidth = 0;
for (int i = 0; i < getItemCount(); i++) {
//初始化,将在屏幕内的view填充
View itemView = recycler.getViewForPosition(i);
addView(itemView);
//测量itemView的宽高
measureChildWithMargins(itemView, 0, 0);
int width = getDecoratedMeasuredWidth(itemView);
int height = getDecoratedMeasuredHeight(itemView);
//根据itemView的宽高进行布局
layoutDecorated(itemView, autualWidth, 0, autualWidth + width, height);
autualWidth += width;
//如果当前布局过的itemView的宽度总和大于RecyclerView的宽,则不再进行布局
if (autualWidth > getWidth()) {
break;
}
}
}
onLayoutChildren() 方