📌  相关文章
📜  如何在Android的RecyclerView中使用SnapHelper?(1)

📅  最后修改于: 2023-12-03 14:52:39.858000             🧑  作者: Mango

如何在Android的RecyclerView中使用SnapHelper?

SnapHelper是Android Support库中新添加的一个类,可以让RecyclerView滑动到某个Item位置后自动停止,而不是滑过去。这种效果在某些情况下是非常有用的,比如做轮播图、图片查看器等。

接下来,我们将介绍如何在Android的RecyclerView中使用SnapHelper。

添加依赖

首先,在build.gradle文件中添加RecyclerView的依赖:

implementation 'androidx.recyclerview:recyclerview:1.0.0'
实现SnapHelper

接下来,我们将实现一个SnapHelper,让RecyclerView实现滑动后自动停止的效果。

public class CustomSnapHelper extends SnapHelper {

    private static final float MILLISECONDS_PER_INCH = 100f;
    private RecyclerView mRecyclerView;
    private LinearSmoothScroller mSmoothScroller;

    @Override
    public void attachToRecyclerView(@Nullable RecyclerView recyclerView) throws IllegalStateException {
        super.attachToRecyclerView(recyclerView);
        mRecyclerView = recyclerView;
        mSmoothScroller = new LinearSmoothScroller(recyclerView.getContext()) {
            // 此处设置滑动速度,可以根据自己的需要调整
            @Override
            protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
                return MILLISECONDS_PER_INCH / displayMetrics.densityDpi;
            }
        };
    }

    @Override
    public int[] calculateDistanceToFinalSnap(@NonNull RecyclerView.LayoutManager layoutManager,
                                              @NonNull View targetView) {
        int[] out = new int[2];
        if (layoutManager.canScrollHorizontally()) {
            out[0] = distanceToCenter(layoutManager, targetView,
                    getHorizontalHelper(layoutManager));
        } else {
            out[0] = 0;
        }
        if (layoutManager.canScrollVertically()) {
            out[1] = distanceToCenter(layoutManager, targetView,
                    getVerticalHelper(layoutManager));
        } else {
            out[1] = 0;
        }
        return out;
    }

    @Override
    public View findSnapView(RecyclerView.LayoutManager layoutManager) {
        if (layoutManager instanceof LinearLayoutManager) {
            // 滑动停止后的位置,可以根据自己的需要调整
            int firstChildPos = ((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition();
            int lastChildPos = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition();
            int childCount = lastChildPos - firstChildPos + 1;
            if (childCount > 0) {
                View child = layoutManager.findViewByPosition(firstChildPos);
                View lastChild = layoutManager.findViewByPosition(lastChildPos);
                int screenWidth = mRecyclerView.getWidth();
                int screenHeight = mRecyclerView.getHeight();
                return getSnapView(layoutManager, child, lastChild, screenWidth, screenHeight);
            }
        }
        return null;
    }

    private View getSnapView(RecyclerView.LayoutManager layoutManager, View child, View lastChild,
                             int screenWidth, int screenHeight) {
        int childLeft = getHorizontalHelper(layoutManager).getDecoratedStart(child);
        int childRight = getHorizontalHelper(layoutManager).getDecoratedEnd(child);
        int childTop = getVerticalHelper(layoutManager).getDecoratedStart(child);
        int childBottom = getVerticalHelper(layoutManager).getDecoratedEnd(child);
        int lastChildLeft = getHorizontalHelper(layoutManager).getDecoratedStart(lastChild);
        int lastChildRight = getHorizontalHelper(layoutManager).getDecoratedEnd(lastChild);
        int lastChildTop = getVerticalHelper(layoutManager).getDecoratedStart(lastChild);
        int lastChildBottom = getVerticalHelper(layoutManager).getDecoratedEnd(lastChild);
        if (lastChildRight < screenWidth && lastChildBottom < screenHeight) {
            return lastChild;
        }
        if (childLeft >= screenWidth / 2) {
            return child;
        } else if (childRight <= screenWidth / 2) {
            int lastChildIndex = layoutManager.getPosition(lastChild);
            return layoutManager.findViewByPosition(lastChildIndex - 1);
        } else {
            return child;
        }
    }

    private int distanceToCenter(RecyclerView.LayoutManager layoutManager, View targetView,
                                 OrientationHelper helper) {
        int childCenter = helper.getDecoratedStart(targetView) + helper.getDecoratedMeasurement(targetView) / 2;
        int containerCenter;
        if (layoutManager.getClipToPadding()) {
            containerCenter = helper.getStartAfterPadding() + helper.getTotalSpace() / 2;
        } else {
            containerCenter = helper.getEnd() / 2;
        }
        return childCenter - containerCenter;
    }

    @Override
    public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state,
                                       int position) {
        mSmoothScroller.setTargetPosition(position);
        startSmoothScroll(mSmoothScroller);
    }

    private OrientationHelper getHorizontalHelper(RecyclerView.LayoutManager layoutManager) {
        if (layoutManager.canScrollHorizontally()) {
            return OrientationHelper.createHorizontalHelper(layoutManager);
        }
        return null;
    }

    private OrientationHelper getVerticalHelper(RecyclerView.LayoutManager layoutManager) {
        if (layoutManager.canScrollVertically()) {
            return OrientationHelper.createVerticalHelper(layoutManager);
        }
        return null;
    }
}
使用SnapHelper

最后,我们将在RecyclerView中使用我们实现的SnapHelper。

CustomSnapHelper snapHelper = new CustomSnapHelper();
snapHelper.attachToRecyclerView(recyclerView);

以上便是在Android的RecyclerView中使用SnapHelper的完整介绍,希望对大家有所帮助。