使用 RecyclerView 實現 Gallery 畫廊效果,并控制 Item 停留位置

hokj2681 7年前發布 | 14K 次閱讀 Android開發 移動開發 RecyclerView

RecyclerView 作為一個列表滑動控件,我們都知道它既可以橫向滑動,也可以豎直滑動,可以實現線性布局管理,瀑布流布局管理,還有 GridView 布局管理。其實我們可以控制其 Item 的停留位置,并使其實現畫廊效果。如果大家熟悉 SnapHelper 的話,估計大家就都會了。

什么是 SnapHelper

SnapHelper 的實現原理就是是監聽 RecyclerView.OnFlingListener 中的 onFling 接口。support library 中只提供了一個繼承類 LinearSnapHelper ,LinearSnapHelper 是抽象類 SnapHelper 的具體實現。

通過 LinearSnapHelper,我們就可以使 RecyclerView 實現類似 ViewPager 的功能,無論怎么滑動最終都會停留在列表頁面正中間。

SnapHelper 和 ViewPager 的區別就是 ViewPager 一次只能滑動一頁,而 RecyclerView + SnapHelper 的方式可以實現一次滑動好幾頁。

效果如下:

居中實現方式

使用 SnapHelper 配合 RecyclerView 實現控制 Item 位置居中顯示,非常簡單,官方默認提供的 LinearSnapHelper 就是居中的,我們直接使用即可。

代碼如下:

LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
recyclerView.setLayoutManager(linearLayoutManager);
new LinearSnapHelper().attachToRecyclerView(recyclerView);

自定義 SnapHelper

官方提供的默認是居中顯示,其實我們也可以自定義,比如:靠左顯示,讓可見的第一個 Item 居左顯示。

效果圖如下

自定義 SnapHelper ,一般需要實現兩個方法:

  • int[] calculateDistanceToFinalSnap(RecyclerView.LayoutManager layoutManager, View targetView) 當拖拽或滑動結束時會回調該方法,返回一個out = int[2],out[0]x軸,out[1] y軸,這就是我們需要修改的位置偏移量
  • View findSnapView(RecyclerView.LayoutManager layoutManager) 該方法返回上面方法中需要的 targetView 。

代碼如下

public classCustomSnapHelperextendsLinearSnapHelper{
    private OrientationHelper mHorizontalHelper;

    @Override
    public int[] calculateDistanceToFinalSnap(RecyclerView.LayoutManager layoutManager, View targetView) {
        int[] out = new int[2];
        //判斷支持水平滾動,修改水平方向的位置,是修改的out[0]的值
        if (layoutManager.canScrollHorizontally()) {
            out[0] = distanceToStart(targetView, getHorizontalHelper(layoutManager));
        } else {
            out[0] = 0;
        }
        return out;
    }

    privateintdistanceToStart(View targetView, OrientationHelper helper){
        return helper.getDecoratedStart(targetView) - helper.getStartAfterPadding();
    }

    @Override
    publicViewfindSnapView(RecyclerView.LayoutManager layoutManager){
        return findStartView(layoutManager, getHorizontalHelper(layoutManager));
    }

    privateViewfindStartView(RecyclerView.LayoutManager layoutManager,
                               OrientationHelper helper) {

        if (layoutManager instanceof LinearLayoutManager) {
            int firstChild = ((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition();
            int lastChild = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition();
            if (firstChild == RecyclerView.NO_POSITION) {
                return null;
            }
            //這行的作用是如果是最后一個,翻到最后一條,解決顯示不全的問題
            if (lastChild == layoutManager.getItemCount() - 1) {
                return layoutManager.findViewByPosition(lastChild);
            }

            View child = layoutManager.findViewByPosition(firstChild);
            //獲取偏左顯示的Item
            if (helper.getDecoratedEnd(child) >= helper.getDecoratedMeasurement(child) / 2
                    && helper.getDecoratedEnd(child) > 0) {
                return child;
            } else {
                return layoutManager.findViewByPosition(firstChild + 1);
            }
        }

        return super.findSnapView(layoutManager);
    }


    privateOrientationHelpergetHorizontalHelper(
            RecyclerView.LayoutManager layoutManager) {
        if (mHorizontalHelper == null) {
            mHorizontalHelper = OrientationHelper.createHorizontalHelper(layoutManager);
        }
        return mHorizontalHelper;
    }
}

調用自定義的 SnapHelper 代碼如下,配合 RecyclerView:

CustomSnapHelper mMySnapHelper = new CustomSnapHelper();
mMySnapHelper.attachToRecyclerView(rv);

最后,其實垂直方向也可以實現哦,大家可以嘗試一下垂直方向的使用方式是不是非常簡單。

 

 

來自:http://godcoder.me/2017/02/06/使用 RecyclerView 實現 Gallery 畫廊效果,并控制 Item 停留位置/

 

 本文由用戶 hokj2681 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!