上下滑切换翻页大概是这样的效果:git
目前网上有诸多如 “仿抖音上下滑...” “仿花椒映客直播...” 之类的技术分享,都有讲述实现上下滑切换页面的方案,其中以 ViewPager
和 RecyclerView
+ SnapHelper
两种方案为多,可是都有明显的缺点。如下是一些我的的见解:github
ViewPager
自带的滑动效果彻底知足场景,并且支持 Fragment
和 View
等UI绑定,只要对布局和触摸事件部分做一些修改,就能够把横向的 ViewPager
改为竖向。布局
可是没有复用是个最致命的问题。在 onLayout
方法中,全部子View会实例化并一字排开在布局上。当Item数量很大时,将会是很大的性能浪费。性能
其次是可见性判断的问题。不少人会觉得 Fragment
在 onResume
的时候就是可见的,而 ViewPager
中的 Fragment
就是个反例,尤为是多个 ViewPager
嵌套时,会同时有多个父 Fragment
多个子 Fragment
处于 onResume
的状态,却只有其中一个是可见的。除非放弃 ViewPager
的预加载机制。在页面内容曝光等重要的数据上报时,就须要判断不少条件:onResumed
、 setUserVisibleHint
、 setOnPageChangeListener
等。动画
最后是嵌套滑动的问题。同向嵌套滑动是很常见的场景,Google 新出的滑动布局基本都使用 NestedScrolling 机制来解决嵌套滑动。可是 ViewPager 依然须要开发者本身来处理复杂的滑动冲突。code
RecyclerView
+ SnapHelper
的方案比 ViewPager
好得多,既有对 View
的复用,滑动事件也已经处理好。cdn
可是依然没法双向无限滑动。咱们能够在 getItemCount
方法中返回 Integer.MAX_VALUE 来伪装无限个滑动元素。可是为了从头开始就能够下拉滑到上一个,元素列表的索引就不能初始化为0,那初始值为 Integer.MAX_VALUE/2 ? 不管怎么掩饰,理论上仍是有滑动到头的一天。索引
使用两个 View 轮流切换就能完成上下滑的场景。这种方案也有APP在用,可是网上几乎找不到源码。所以我把它抽成独立的库放在Github仓库:致力于打造通用、易用和流畅的上下滑动翻页布局SlidableLayout。接口
SlidableLayout 本质是一个包含两个相同大小子 View
的 FrameLayout
。两个子 View
分别做为 TopView 和 BackView 。事件
静止状态下,用户只会看见 TopView ,而 BackView 被移除或隐藏。
手指向上拖动时, TopView 在y轴上向上偏移, BackView 开始出现,并且 BackView 的顶部与 TopView 的底部相接。
手指向上拖动必定距离后放手,TopView 继续在y轴上作动画直到彻底消失, BackView 向上直到彻底出现。而后 TopView 和 BackView 互换身份,原来的 BackView 成为如今的 TopView ,原来的 TopView 被移除或隐藏,成为下一次滑动的 BackView 。互换后完成一次滑动。
反之,手指向下滑动亦然。
同时要考虑手指放手后,滑动距离不够或者速度不够时,TopView 会沿着y轴回弹到原来的位置。 BackView 也跟着原路返回,直到被移除或隐藏。
SlidableLayout 还实现了 NestedScrollingChild 接口,使其可以与自定义的下拉刷新布局嵌套滑动。
源码和使用例子参照 github.com/YvesCheung/… 。若有不一样意的地方,请在 Github 留下 Issue。