LooperLayoutManage
new 一个类 LooperLayoutManager继承LinearLayoutManager
用来调整间距 private int mMargin;
import android.content.Context;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
public class LooperLayoutManager extends LinearLayoutManager {
private static final String TAG = "LooperLayoutManager";
public LooperLayoutManager(Context context) {
super(context);
}
private int mMargin=36;
@Override
public RecyclerView.LayoutParams generateDefaultLayoutParams() {
return new RecyclerView.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
}
@Override
public boolean canScrollHorizontally() {
return true;
}
@Override
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
if (getItemCount() <= 0) {
return;
}
//标注1.如果当前时准备状态,直接返回
if (state.isPreLayout()) {
return;
}
//标注2.将视图分离放入scrap缓存中,以准备重新对view进行排版
detachAndScrapAttachedViews(recycler);
int autualWidth = 0;
for (int i = 0; i < getItemCount(); i++) {
//标注3.初始化,将在屏幕内的view填充
View itemView = recycler.getViewForPosition(i);
addView(itemView);
//标注4.测量itemView的宽高
measureChildWithMargins(itemView, 0, 0);
int width = getDecoratedMeasuredWidth(itemView);
int height = getDecoratedMeasuredHeight(itemView);
//标注5.根据itemView的宽高进行布局
layoutDecorated(itemView, autualWidth, 0, autualWidth + width, height);
autualWidth += width+mMargin;
// //标注6.如果当前布局过的itemView的宽度总和大于RecyclerView的宽,则不再进行布局
// if (autualWidth > getWidth()) {
// break;
// }
}
}
@Override
public int scrollHorizontallyBy(int dx, RecyclerView.Recycler recycler, RecyclerView.State state) {
//标注1.横向滑动的时候,对左右两边按顺序填充itemView
int travl = fill(dx, recycler, state);
if (travl == 0) {
return 0;
}
//2.滑动
offsetChildrenHorizontal(-travl);
// offsetChildrenHorizontal(travl * -1);
//3.回收已经不可见的itemView
recyclerHideView(dx, recycler, state);
return travl;
}
/**
* 左右滑动的时候,填充
*/
private RecyclerView.Recycler mRecycle;
public int fill(int dx, RecyclerView.Recycler recycler, RecyclerView.State state) {
if (dx > 0) {
//标注1.向左滚动
View lastView = getChildAt(getChildCount() - 1);
if (lastView == null) {
return 0;
}
int lastPos = getPosition(lastView);
//标注2.可见的最后一个itemView完全滑进来了,需要补充新的
if (lastView.getRight() < getWidth()) {
View scrap = null;
//标注3.判断可见的最后一个itemView的索引,
// 如果是最后一个,则将下一个itemView设置为第一个,否则设置为当前索引的下一个
if (lastPos == getItemCount() - 1) {
if (looperEnable) {
scrap = recycler.getViewForPosition(0);
} else {
dx = 0;
}
} else {
scrap = recycler.getViewForPosition(lastPos + 1);
}
if (scrap == null) {
return dx;
}
//标注4.将新的itemViewadd进来并对其测量和布局
addView(scrap);
measureChildWithMargins(scrap, 0, 0);
int width = getDecoratedMeasuredWidth(scrap);
int height = getDecoratedMeasuredHeight(scrap);
layoutDecorated(scrap,lastView.getRight()+mMargin, 0,
lastView.getRight() + width+mMargin, height);
return dx;
}
} else {
//向右滚动
View firstView = getChildAt(0);
if (firstView == null) {
return 0;
}
int firstPos = getPosition(firstView);
if (firstView.getLeft() >= 0) {
View scrap = null;
if (firstPos == 0) {
if (looperEnable) {
scrap = recycler.getViewForPosition(getItemCount() - 1);
} else {
dx = 0;
}
} else {
scrap = recycler.getViewForPosition(firstPos - 1);
}
if (scrap == null) {
return 0;
}
addView(scrap, 0);
measureChildWithMargins(scrap,0,0);
int width = getDecoratedMeasuredWidth(scrap);
int height = getDecoratedMeasuredHeight(scrap);
layoutDecorated(scrap, firstView.getLeft() - width-mMargin, 0,
firstView.getLeft() -mMargin, height);
}
}
return dx;
}
/**
* 回收界面不可见的view
*/
private void recyclerHideView(int dx, RecyclerView.Recycler recycler, RecyclerView.State state) {
for (int i = 0; i < getChildCount(); i++) {
View view = getChildAt(i);
if (view == null) {
continue;
}
if (dx > 0) {
//标注1.向左滚动,移除左边不在内容里的view
if (view.getRight() < 0) {
removeAndRecycleView(view, recycler);
Log.d(TAG, "循环: 移除 一个view childCount=" + getChildCount());
}
} else {
//标注2.向右滚动,移除右边不在内容里的view
if (view.getLeft() > getWidth()) {
removeAndRecycleView(view, recycler);
Log.d(TAG, "循环: 移除 一个view childCount=" + getChildCount());
}
}
}
}
private boolean looperEnable;
public void setLooperEnable(boolean b) {
this.looperEnable = b;
}
public void setMargin(int margin){
this.mMargin = margin;
}
}
MyAdapter
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.VH> {
private List<String> list = new ArrayList<>();
private Context context;
public MyAdapter(Context context, List<String> lists) {
this.context = context;
list.clear();
this.list.addAll(lists);
}
@NonNull
@Override
public VH onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.item_home, parent, false);
return new VH(view);
}
@Override
public void onBindViewHolder(@NonNull VH holder, int position) {
holder.mTitleTv.setText(list.get(position));
}
//1、设置item数量无限多
@Override
public int getItemCount() {
return list.size();
}
class VH extends RecyclerView.ViewHolder {
TextView mTitleTv;
public VH(@NonNull View itemView) {
super(itemView);
mTitleTv = itemView.findViewById(R.id.title);
}
}
}
我在考虑item的布局这么简单写还是不写呢,想想还是写吧
item_home.xml
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/item"
android:layout_width="150dp"
android:layout_height="240dp"
app:cardCornerRadius="16dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/teal_200">
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/white"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent">
</TextView>
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
使用方法
mRecyclerView.setAdapter(new MyAdapter(getContext(),list));
mLayoutManager = new LooperLayoutManager(getContext());
mLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
mLayoutManager.setLooperEnable(true);
//设置间距
mLayoutManager.setMargin(66);
mRecyclerView.setLayoutManager(mLayoutManager);