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

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