使用 RecyclerView 实现 Gallery 画廊效果,并控制 Item 停留位置

hokj2681 7年前
   <p>RecyclerView 作为一个列表滑动控件,我们都知道它既可以横向滑动,也可以竖直滑动,可以实现线性布局管理,瀑布流布局管理,还有 GridView 布局管理。其实我们可以控制其 Item 的停留位置,并使其实现画廊效果。如果大家熟悉 SnapHelper 的话,估计大家就都会了。</p>    <h3>什么是 SnapHelper</h3>    <p>SnapHelper 的实现原理就是是监听 RecyclerView.OnFlingListener 中的 onFling 接口。support library 中只提供了一个继承类 LinearSnapHelper ,LinearSnapHelper 是抽象类 SnapHelper 的具体实现。</p>    <p>通过 LinearSnapHelper,我们就可以使 RecyclerView 实现类似 ViewPager 的功能,无论怎么滑动最终都会停留在列表页面正中间。</p>    <p>SnapHelper 和 ViewPager 的区别就是 ViewPager 一次只能滑动一页,而 RecyclerView + SnapHelper 的方式可以实现一次滑动好几页。</p>    <p>效果如下:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/7f4d45cf0430580c2b80cc388bba0ff3.gif"></p>    <h3>居中实现方式</h3>    <p>使用 SnapHelper 配合 RecyclerView 实现控制 Item 位置居中显示,非常简单,官方默认提供的 LinearSnapHelper 就是居中的,我们直接使用即可。</p>    <p>代码如下:</p>    <pre>  <code class="language-java">LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);  recyclerView.setLayoutManager(linearLayoutManager);  new LinearSnapHelper().attachToRecyclerView(recyclerView);  </code></pre>    <h3>自定义 SnapHelper</h3>    <p>官方提供的默认是居中显示,其实我们也可以自定义,比如:靠左显示,让可见的第一个 Item 居左显示。</p>    <p>效果图如下</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/7caaf0785be70cd656895eaf83fbc660.gif"></p>    <p>自定义 SnapHelper ,一般需要实现两个方法:</p>    <ul>     <li>int[] calculateDistanceToFinalSnap(RecyclerView.LayoutManager layoutManager, View targetView) 当拖拽或滑动结束时会回调该方法,返回一个out = int[2],out[0]x轴,out[1] y轴,这就是我们需要修改的位置偏移量</li>     <li>View findSnapView(RecyclerView.LayoutManager layoutManager) 该方法返回上面方法中需要的 targetView 。</li>    </ul>    <p>代码如下</p>    <pre>  <code class="language-java">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;      }  }  </code></pre>    <p>调用自定义的 SnapHelper 代码如下,配合 RecyclerView:</p>    <pre>  <code class="language-java">CustomSnapHelper mMySnapHelper = new CustomSnapHelper();  mMySnapHelper.attachToRecyclerView(rv);  </code></pre>    <p>最后,其实垂直方向也可以实现哦,大家可以尝试一下垂直方向的使用方式是不是非常简单。</p>    <p> </p>    <p> </p>    <p>来自:http://godcoder.me/2017/02/06/使用 RecyclerView 实现 Gallery 画廊效果,并控制 Item 停留位置/</p>    <p> </p>