1.Gif效果
2. Activity
public class MainActivity extends BaseActivity {
private static final String TAG = "xiao";
private final List<String> books = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
testRecyclerView();
}
private void testRecyclerView() {
for (int i = 0; i < 13; i++) {
books.add("书" + i);
}
RecyclerView rcv = findViewById(R.id.recyclerview);
BookAdapter bookAdapter = new BookAdapter();
// spanCount为2
GridLayoutManager layoutManager = new BookLayoutManager(this, 2,
LinearLayoutManager.HORIZONTAL, false);
rcv.setLayoutManager(layoutManager);
rcv.setAdapter(bookAdapter);
// 左右滑动固定翻页的效果实现
SnapHelper pagerSnapHelper = new GridPagerSnapHelper();
pagerSnapHelper.attachToRecyclerView(rcv);
}
private enum BookType {
EDUCATION,
EMPRISE,
DEVELOP
}
private static class GridPagerSnapHelper extends SnapHelper {
private static final int MAX_SCROLL_ON_FLING_DURATION = 100; // 最大滚动时间
private RecyclerView recyclerView;
@Override
public void attachToRecyclerView(@Nullable RecyclerView recyclerView) throws IllegalStateException {
super.attachToRecyclerView(recyclerView);
this.recyclerView = recyclerView;
}
@Nullable
@Override
public int[] calculateDistanceToFinalSnap(@NonNull RecyclerView.LayoutManager layoutManager, @NonNull View targetView) {
int[] out = new int[2];
if (layoutManager.canScrollHorizontally()) {
out[0] = distanceToStart(targetView, OrientationHelper.createHorizontalHelper(layoutManager));
}
return out;
}
@Nullable
@Override
public View findSnapView(RecyclerView.LayoutManager layoutManager) {
return findStartView(layoutManager, OrientationHelper.createHorizontalHelper(layoutManager));
}
@Override
public int findTargetSnapPosition(RecyclerView.LayoutManager layoutManager, int velocityX, int velocityY) {
if (layoutManager instanceof GridLayoutManager) {
GridLayoutManager gridLayoutManager = (GridLayoutManager) layoutManager;
// 获取GridLayoutManager的spanCount
int spanCount = gridLayoutManager.getSpanCount();
// 获取当前可见的第一个item位置
int firstVisibleItem = gridLayoutManager.findFirstVisibleItemPosition();
if (firstVisibleItem == RecyclerView.NO_POSITION) {
return RecyclerView.NO_POSITION;
}
int targetPosition;
// 根据水平滚动方向的速度来确定下一页或上一页
if (velocityX > 0) {
// 向右滚动,移动到下一页
targetPosition = firstVisibleItem + spanCount;
} else {
// 向左滚动,移动到上一页
targetPosition = firstVisibleItem - spanCount;
}
// 确保目标位置不越界
int itemCount = layoutManager.getItemCount();
targetPosition = Math.min(Math.max(0, targetPosition), itemCount - 1);
return targetPosition;
}
return RecyclerView.NO_POSITION;
}
private int distanceToStart(View targetView, OrientationHelper helper) {
return helper.getDecoratedStart(targetView) - helper.getStartAfterPadding();
}
private View findStartView(RecyclerView.LayoutManager layoutManager, OrientationHelper helper) {
if (!(layoutManager instanceof GridLayoutManager)) {
return null;
}
int firstChild = ((GridLayoutManager) layoutManager).findFirstVisibleItemPosition();
if (firstChild == RecyclerView.NO_POSITION) {
return null;
}
View firstChildView = layoutManager.findViewByPosition(firstChild);
int firstChildStart = helper.getDecoratedStart(firstChildView);
if (firstChildStart >= helper.getStartAfterPadding() + (helper.getTotalSpace() / 2)) {
return null;
}
return firstChildView;
}
}
private static class BookLayoutManager extends GridLayoutManager {
public BookLayoutManager(Context context, int spanCount, int orientation, boolean reverseLayout) {
super(context, spanCount, orientation, reverseLayout);
}
@Override
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
super.onLayoutChildren(recycler, state);
int parentWidth = getWidth();
int parentHeight = getHeight();
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
ViewGroup.LayoutParams params = child.getLayoutParams();
Log.d(TAG, "getSpanCount(): " + getSpanCount());
params.width = parentWidth / getSpanCount();
params.height = parentHeight / getSpanCount();
child.setLayoutParams(params);
}
}
}
private class BookAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(MainActivity.this);
View view = inflater.inflate(R.layout.book_item, null);
switch (viewType) {
case 0:
return new EducationViewHolder(view);
case 1:
return new EmpriseViewHolder(view);
case 2:
return new DevelopViewHolder(view);
}
throw new IllegalArgumentException("unknown type...");
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
View itemView = holder.itemView;
TextView book = itemView.findViewById(R.id.book);
if (getItemViewType(position) == BookType.EDUCATION.ordinal()) {
book.setText("教育型书籍, position: " + position);
}
if (getItemViewType(position) == BookType.EMPRISE.ordinal()) {
book.setText("武侠型书籍, position: " + position);
}
if (getItemViewType(position) == BookType.DEVELOP.ordinal()) {
book.setText("成长型书籍, position: " + position);
}
}
@Override
public int getItemCount() {
return books.size();
}
@Override
public int getItemViewType(int position) {
if (position == 1) return BookType.DEVELOP.ordinal();
if (position == 2) return BookType.EMPRISE.ordinal();
return BookType.EDUCATION.ordinal();
}
private class EducationViewHolder extends RecyclerView.ViewHolder {
public EducationViewHolder(@NonNull View itemView) {
super(itemView);
}
}
private class EmpriseViewHolder extends RecyclerView.ViewHolder {
public EmpriseViewHolder(@NonNull View itemView) {
super(itemView);
}
}
private class DevelopViewHolder extends RecyclerView.ViewHolder {
public DevelopViewHolder(@NonNull View itemView) {
super(itemView);
}
}
}
}
3. item_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<TextView
android:id="@+id/book"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</androidx.constraintlayout.widget.ConstraintLayout>
GIF录制工具链接: 点击这里跳转获取