文章介绍 Android 24.2.0 支持库中的 SnapHelper,目标是让横向 RecyclerView 在拖动或 fling 结束后完整对齐首个条目,获得类似 Google Play 的滑动效果。 实现通过继承 LinearSnapHelper 重写对齐距离计算和目标视图选择,将默认的居中对齐改为首项对齐。文中还分析 Scroll/Fling 监听、snapToTargetExistingView 与平滑滚动的协作方式,以及普通滑动和 fling 的处理差异。
横向滑动RecyclerView一般都会要求类似Viewpager的效果就是要保证第一个item是全部展现的。我之前的处理方法就是添加滑动监听然后当滑动停止时计算显示的首个可见及完全可见的position然后再进行滑动达到这个效果。不过在实现时会发现滑动速度太快,这里又需要重写LinearSmoothScroller。然后还有一个重要的效果就是Fling时要保证滑动停止时直接是完全显示首个Item,这里之前的方法是预测Fling的滑动距离然后找到最近的position之后再用LayoutManager的scrolltoposition()滑动过去。不过这样就没有fling的速度效果了。因为smoothscroll都是匀速的,现在recyclerView 24.2.0的支持库提供了SnapHelper现在我们可以完全模拟实现googleplay的效果了。
SnapHelper
SnapHelper 是一个抽象类,需要实现三个方法:
看这三个方法介绍就会发现已经可以实现GooglePlay上的效果了。下面以横向LinearLayoutManager以首项对齐为基础我们来简单实现下。
创建MySnapHelper 继承 LinearSnapHelper
LinearSnapHelper 默认实现fling的相关操作,LinearSnapHelper 是居中对齐的,如果是这样的需求可以直接使用
写RecyclerView那些东西(略)
使用我们定义好的MySnapHelper
看下效果吧

原理分析
最开始扯了一堆我之前实现的想法,那么肯定要分析下SnapHelper做了些什么吧
- 添加Scroll及Fling的监听
- snapToTargetExistingView,用了定义的两个抽象方法,然后执行滑动,这里的滑动用的是RecyclerView的scroller不是匀速的。
- 对于fling使用了匀速的scroller,这里放慢了滑动的速度,这里重写了onTargetFind,因为默认是保证View的可见性,这里进行了扩展
总结
- 普通的滑动使用了正常的Scroller
- Fling使用了匀速的Scroller