爲何我不用ViewPager或RecyclerView來作上下滑切換

上下滑切換翻頁大概是這樣的效果:git

SlidableLayout

目前網上有諸多如 「仿抖音上下滑...」 「仿花椒映客直播...」 之類的技術分享,都有講述實現上下滑切換頁面的方案,其中以 ViewPagerRecyclerView + SnapHelper 兩種方案爲多,可是都有明顯的缺點。如下是一些我的的見解:github

爲何ViewPager不合適

ViewPager 自帶的滑動效果徹底知足場景,並且支持 FragmentView 等UI綁定,只要對佈局和觸摸事件部分做一些修改,就能夠把橫向的 ViewPager 改爲豎向。佈局

可是沒有複用是個最致命的問題。在 onLayout 方法中,全部子View會實例化並一字排開在佈局上。當Item數量很大時,將會是很大的性能浪費。性能

其次是可見性判斷的問題。不少人會覺得 FragmentonResume 的時候就是可見的,而 ViewPager 中的 Fragment 就是個反例,尤爲是多個 ViewPager 嵌套時,會同時有多個父 Fragment 多個子 Fragment 處於 onResume 的狀態,卻只有其中一個是可見的。除非放棄 ViewPager 的預加載機制。在頁面內容曝光等重要的數據上報時,就須要判斷不少條件:onResumedsetUserVisibleHintsetOnPageChangeListener 等。動畫

最後是嵌套滑動的問題。同向嵌套滑動是很常見的場景,Google 新出的滑動佈局基本都使用 NestedScrolling 機制來解決嵌套滑動。可是 ViewPager 依然須要開發者本身來處理複雜的滑動衝突。code

爲何RecyclerView不合適

RecyclerView + SnapHelper 的方案比 ViewPager 好得多,既有對 View 的複用,滑動事件也已經處理好。cdn

可是依然沒法雙向無限滑動。咱們能夠在 getItemCount 方法中返回 Integer.MAX_VALUE 來僞裝無限個滑動元素。可是爲了從頭開始就能夠下拉滑到上一個,元素列表的索引就不能初始化爲0,那初始值爲 Integer.MAX_VALUE/2 ? 不管怎麼掩飾,理論上仍是有滑動到頭的一天。索引

更優的一種解決方案

使用兩個 View 輪流切換就能完成上下滑的場景。這種方案也有APP在用,可是網上幾乎找不到源碼。所以我把它抽成獨立的庫放在Github倉庫:致力於打造通用、易用和流暢的上下滑動翻頁佈局SlidableLayout接口

SlidableLayout 本質是一個包含兩個相同大小子 ViewFrameLayout 。兩個子 View 分別做爲 TopViewBackView事件

靜止狀態下,用戶只會看見 TopView ,而 BackView 被移除或隱藏。

手指向上拖動時, TopView 在y軸上向上偏移, BackView 開始出現,並且 BackView 的頂部與 TopView 的底部相接。

手指向上拖動必定距離後放手,TopView 繼續在y軸上作動畫直到徹底消失, BackView 向上直到徹底出現。而後 TopViewBackView 互換身份,原來的 BackView 成爲如今的 TopView ,原來的 TopView 被移除或隱藏,成爲下一次滑動的 BackView 。互換後完成一次滑動。

反之,手指向下滑動亦然。

同時要考慮手指放手後,滑動距離不夠或者速度不夠時,TopView 會沿着y軸回彈到原來的位置。 BackView 也跟着原路返回,直到被移除或隱藏。

SlidableLayout 還實現了 NestedScrollingChild 接口,使其可以與自定義的下拉刷新佈局嵌套滑動。

源碼和使用例子參照 github.com/YvesCheung/… 。若有不一樣意的地方,請在 Github 留下 Issue

相關文章
相關標籤/搜索