recyclerView滑动停止后item对齐方式

 

SnapHelper是support-v7:24.2.0新增的,用于控制RecyclerView滑动停止后Item的对齐方式。默认提供了两种对齐方式PagerSnapHelper 与 LinearSnapHelper。PagerSnapHelper 和ViewPage效果一样,一次滑动一页。LinearSnapHelper这是Item居中对齐。使用方式非常简单:
 

PagerSnapHelper mPagerSnapHelper = new PagerSnapHelper();
 mPagerSnapHelper.attachToRecyclerView(mRecyclerView);

效果如下

å¨è¿éæå¥å¾çæè¿°

当然我们可以自定义SnapHelper,来实现我们想要的对齐方式,下面我们来实现一下左对齐

public class MySnapHelper extends LinearSnapHelper{

    /**
     * 水平、垂直方向的度量
     */
    @Nullable
    private OrientationHelper mVerticalHelper;
    @Nullable
    private OrientationHelper mHorizontalHelper;

    @NonNull
    private OrientationHelper getVerticalHelper(@NonNull RecyclerView.LayoutManager layoutManager) {
        if (mVerticalHelper == null) {
            mVerticalHelper = OrientationHelper.createVerticalHelper(layoutManager);
        }
        return mVerticalHelper;
    }

    @NonNull
    private OrientationHelper getHorizontalHelper(@NonNull RecyclerView.LayoutManager layoutManager) {
        if (mHorizontalHelper == null) {
            mHorizontalHelper = OrientationHelper.createHorizontalHelper(layoutManager);
        }
        return mHorizontalHelper;
    }
    
    /**
     * 计算出View对齐到指定位置,所需的x、y轴上的偏移量。
     */
    @Nullable
    @Override
    public int[] calculateDistanceToFinalSnap(@NonNull RecyclerView.LayoutManager layoutManager, @NonNull View targetView) {
        int[] out = new int[2];
        
        // 水平方向滑动时计算x方向,否则偏移为0
        if (layoutManager.canScrollHorizontally()) {
            out[0] = distanceToStart(layoutManager, targetView, getHorizontalHelper(layoutManager));
        } else {
            out[0] = 0;
        }

        // 垂直方向滑动时计算y方向,否则偏移为0
        if (layoutManager.canScrollVertically()) {
            out[1] = distanceToStart(layoutManager, targetView, getVerticalHelper(layoutManager));
        } else {
            out[1] = 0;
        }
        return out;
    }

    private int distanceToStart(RecyclerView.LayoutManager layoutManager, View targetView, OrientationHelper helper) {
        // RecyclerView的边界x值,也就是左侧Padding值
        final int start;
        if (layoutManager.getClipToPadding()) {
            start = helper.getStartAfterPadding();
        } else {
            start = 0;
        }
        return helper.getDecoratedStart(targetView) - start;
    }

    /**
     * 查找需要对齐的View
     */
    @Nullable
    @Override
    public View findSnapView(RecyclerView.LayoutManager layoutManager) {
        if (layoutManager.canScrollVertically()) {
            return findStartView(layoutManager, getVerticalHelper(layoutManager));
        } else {
            return findStartView(layoutManager, getHorizontalHelper(layoutManager));
        }
    }

    private View findStartView(RecyclerView.LayoutManager layoutManager, OrientationHelper helper) {
        int childCount = layoutManager.getChildCount();
        if (childCount == 0) {
            return null;
        }

        View closestChild = null;
        final int start;
        if (layoutManager.getClipToPadding()) {
            start = helper.getStartAfterPadding();
        } else {
            start = 0;
        }
        int absClosest = Integer.MAX_VALUE;
        
        for (int i = 0; i < childCount; i++) {
            final View child = layoutManager.getChildAt(i);
            // ItemView 的左侧座标
            int childStart = helper.getDecoratedStart(child);
            // 计算此ItemView 与 RecyclerView左侧的距离
            int absDistance = Math.abs(childStart - start);

            // 找到那个最靠近左侧的ItemView然后返回
            if (absDistance < absClosest) {
                absClosest = absDistance;
                closestChild = child;
            }
        }
        
        return closestChild;
    }

    /**
     * 找到需要对齐的View的position,主要用于fling 操作
     */
    @Override
    public int findTargetSnapPosition(RecyclerView.LayoutManager layoutManager, int velocityX, int velocityY) {
        // 左对齐和居中对齐一样,无需自定义处理
        return super.findTargetSnapPosition(layoutManager, velocityX, velocityY);
    }
}

上面的注释已将关键地方注明,效果我就不展示了。大家可以下载代码去体验。本篇所有代码已上传至Github

转自:https://blog.csdn.net/qq_17766199/article/details/83147483

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章