Google 在 Android 24.2.0 的support 包中添加了SnapHelper,SnapHelper是对RecyclerView的拓展,结合RecyclerView使用,能很方便的做出一些炫酷的效果。SnapHelper到底有什么功能呢?SnapHelper旨在支持RecyclerView的对齐方式,也就是通过计算对齐RecyclerView中TargetView 的指定点或者容器中的任何像素点。,可能有点不好理解,看了后文的效果和原理分析就好理解了。看一下文档介绍:
SnapHealper 介绍.png
SnapHelper继承自RecyclerView.OnFlingListener
,并实现了它的抽象方法onFling
, 支持SnapHelper的RecyclerView.LayoutManager
必须实现RecyclerView.SmoothScroller.ScrollVectorProvider
接口,或者你自己实现onFling(int,int)
方法手动处理。SnapHeper 有以下几个重要方法:
-
attachToRecyclerView: 将SnapHelper attach 到指定的RecyclerView 上。
-
calculateDistanceToFinalSnap: 复写这个方法计算对齐到TargetView或容器指定点的距离,这是一个抽象方法,由子类自己实现,返回的是一个长度为2的int 数组out,out[0]是x方向对齐要移动的距离,out[1]是y方向对齐要移动的距离。
-
calculateScrollDistance: 根据每个方向给定的速度估算滑动的距离,用于Fling 操作。
-
findSnapView:提供一个指定的目标View 来对齐,抽象方法,需要子类实现
-
findTargetSnapPosition:提供一个用于对齐的Adapter 目标position,抽象方法,需要子类自己实现。
-
onFling:根据给定的x和 y 轴上的速度处理Fling。
LinearSnapHelper & PagerSnapHelper
上面讲了SnapHelper的几个重要的方法和作用,SnapHelper是一个抽象类,要使用SnapHelper,需要实现它的几个方法。而 Google 内置了两个默认实现类,LinearSnapHelper
和PagerSnapHelper
,LinearSnapHelper可以使RecyclerView 的当前Item 居中显示(横向和竖向都支持),PagerSnapHelper看名字可能就能猜到,使RecyclerView 像ViewPager一样的效果,每次只能滑动一页(LinearSnapHelper支持快速滑动), PagerSnapHelper也是Item居中对齐。接下来看一下使用方法和效果。
(1) LinearSnapHelper
LinearSnapHelper
使当前Item居中显示,常用场景是横向的RecyclerView, 类似ViewPager效果,但是又可以快速滑动(滑动多页)。代码如下:
LinearLayoutManager manager = new LinearLayoutManager(getContext());
manager.setOrientation(LinearLayoutManager.VERTICAL);
mRecyclerView.setLayoutManager(manager);
// 将SnapHelper attach 到RecyclrView
LinearSnapHelper snapHelper = new LinearSnapHelper();
snapHelper.attachToRecyclerView(mRecyclerView);
代码很简单,new 一个SnapHelper对象,然后 Attach到RecyclerView 即可。
上面的效果为LayoutManager的方向为VERTICAL,那么接下来看一下横向效果,很简单,和上面的区别只是更改一下LayoutManager的方向,代码如下:
LinearLayoutManager manager = new LinearLayoutManager(getContext());
manager.setOrientation(LinearLayoutManager.HORIZONTAL);
mRecyclerView.setLayoutManager(manager);
// 将SnapHelper attach 到RecyclrView
LinearSnapHelper snapHelper = new LinearSnapHelper();
snapHelper.attachToRecyclerView(mRecyclerView);
简单几行代码就可以用RecyclerView 实现一个类似ViewPager的效果,并且效果更赞。可以快速滑动多页,当前页剧中显示,并且显示前一页和后一页的部分。如果使用ViewPager来做还是有点麻烦的。除了上面的效果外,如果你想要和ViewPager 一样,限制一次只让它滑动一页,那么你就可以使用PagerSnapHelper了。
(2) PagerSnapHelper (在Android 25.1.0 support 包加入的)
PagerSnapHelper
的展示效果和LineSnapHelper
是一样的,只是PagerSnapHelper 限制一次只能滑动一页,不能快速滑动。代码如下:
PagerSnapHelper snapHelper = new PagerSnapHelper();
snapHelper.attachToRecyclerView(mRecyclerView);
此外,在Github上发现一个实现了好几种Snap 效果的库,比如,start对齐、end对齐,top 对齐等等。有兴趣的可以去弄来玩一下,地址:[Snap 效果库]。(https://github.com/rubensousa/RecyclerViewSnap)。
PS:有些同学发现自己item不能全屏,也就是match parent没有效果。问题在于在Adapter的onCreateViewHolder创建子view的时候要把parent传进去;
正确写法
LayoutInflater.from(context).inflate(R.layout.item_view,parent,false);
错误写法
LayoutInflater.from(context).inflate(R.layout.item_view,null);