手把手講解ViewPager翻頁特效:關鍵代碼

前言

2020年後第一篇,來點輕鬆的話題吧。在家辦公, UI美眉心血來潮要搞一個滑動特效。 ViewPager+TabLayout ,老生常談的東西了。 ViewPager 是基礎的滑動切換控件, TabLayout 是 和 ViewPager配合使用的標題欄部分(但是 TabLayout也可以脫離ViewPager 獨立使用). 根據查到的資料顯示,谷歌工程師在 ViewPager創立之時,就給風騷的動畫特效預留了接口,我們可以很方便地去使用這個接口進行動畫編程,但是 TabLayout就比較悲情,不但動畫沒預留接口,甚至一些常規操作的接口都沒有提供,所以網上也出現了一些人按照 原 TabLayout的代碼,自己去創造新的xxTabLayout控件。

本文將提供 ViewPager+TabLayout 的實例效果開發思路 ,以及Demo ****github工程。有興趣的童鞋們希望可以留言多多交流。

Demo地址:https://github.com/18598925736/StudyTabLayout/tree/hank_v1

正文大綱

  • 參考效果
  • 前置技能
  • 實現思路
  • 關鍵代碼
  • 思維拓展

承接前篇。

關鍵代碼

有了思路,那麼IT民工現在開始搬磚。

一,動畫拆分各個擊破

1) 子view重疊排布

原本的子view都是橫向,從左到右排布,默認的排布方式並沒有相互覆蓋,所以我們可以考慮使用視圖動畫.

(****為什麼是視圖動畫,而不是屬性動畫?因為沒必要,當前的需求我只需要視覺效果上的位置變化,不需要子view的交互事件,用屬性動畫理論上應該也可以,但是直覺會存在交互問題,有時間再試試****)

使用視圖動畫,將所有子view層疊在一起。原本都是橫向排布,所以只需要將所有的view進行x軸位移,即可。

上代碼:

手把手講解ViewPager翻頁特效:關鍵代碼

公式的推導很簡單,就是讓右邊的子view向左平移 -position個自身寬度。

效果為:

手把手講解ViewPager翻頁特效:關鍵代碼

滑動之後,不再出現其他子view。

2) 讓多個子view之間呈現x軸上的位置差

雖然重疊在了一起,但是我還需要讓右邊的子view呈現位置偏差。並且,越往右偏差越大。

上代碼:

手把手講解ViewPager翻頁特效:關鍵代碼

效果:

手把手講解ViewPager翻頁特效:關鍵代碼

3) 讓多個子view之間呈現縮放差

x軸上的位置差雖然有了,但是原圖上,越往右越小,所以還需要做出x,y方向上的縮放

上代碼:

手把手講解ViewPager翻頁特效:關鍵代碼

效果:

手把手講解ViewPager翻頁特效:關鍵代碼

4) 監聽滑動position,做出透明度逐漸變化

視覺效果都有了,那麼可以開始做動畫效果。

經過對position的觀察,我們知道position會以小數的形式漸變。原圖中,向左滑出的view,會以一個透明度慢慢減小的方式消失,那麼先來完成這一步> 。

手把手講解ViewPager翻頁特效:關鍵代碼

效果:

手把手講解ViewPager翻頁特效:關鍵代碼

5) 監聽滑動position,做出左滑時 當前view的平移動畫

最後一步,滑出消失的view雖然透明度的動畫完成了,但是原圖中,還有一個漸漸向左移動的動畫。

上代碼:

手把手講解ViewPager翻頁特效:關鍵代碼

效果:

手把手講解ViewPager翻頁特效:關鍵代碼

最終效果和原圖差不多。

二,聲明幾個坑

如果有人按照我的思路去實現上面的效果,很有可能失敗,因為其中幾個坑。

1.ViewGroup.clipChildren屬性

任何一個 ViewGroup的子類都具備的屬性,它的作用是,決定是否消減掉 子view超出自身繪製範圍的部分

意思就是說,子view的繪製範圍其實是無限大的,但是它能顯示的範圍由父 viewGroup決定,這個屬性為true,父view不允許子view超出自身的部分顯示出來,反之,則是允許超出。這個屬性默認是 true。所以,如果發現 上述效果中某些部分顯示不出來,就要看看 ViewPager(它是一個 ViewGroup)的 clipChildren屬性是否為 true,如果是 true,設置成 false試試。如果還是不行,看看 ViewPager的父容器 的 clipChildren屬性是否為 false。以此類推。

2.ViewPager.setPageTranformer(booleanreverseDrawingOrder,PageTransformertransformer) 方法有兩個參數,第一個是 bool值,它能決定子view的繪製順序。如果按照上述思路實現效果發現,是右邊的子view覆蓋了左邊的子view,那麼就要看看是不是這個值是不是true。如果不是ture,改成true再嘗試。

3.第2點中,如果不想把 reverseDrawingOrder 設置為 true,也有辦法解決。 androidView體系中存在一個 z軸概念, z值越大,就越在上層,其實,也可以使用改變子 view, z屬性的辦法來解決覆蓋效果錯誤的問題。(但是Z軸的設置與版本有關,要區分設備版本,不然低版本上可能程序崩潰)

思維拓展

還記得前文講過的麼,拿到了View之後,再根據滑動時的參數變化,我們幾乎可以對它為所欲為,那麼我們能做的,就不僅僅是 本次的目標效果,像是類似這種滑動特效,還有很多風騷的操作可以玩。像是:

手把手講解ViewPager翻頁特效:關鍵代碼

手把手講解ViewPager翻頁特效:關鍵代碼

沒有做不到,只有想不到。想到之後,最終能做成什麼效果,就要看自己的數學造詣夠不夠高了。

這次研究最大的收穫,並不是知道了pageTransformer這個接口,而是一種解耦的編程思維,比如我們希望給一個View控件加特效,可以直接在,原本View控件裡面去修改代碼,重寫onTouchEvent來響應滑動事件,或者重寫draw/onDraw進行另外的繪製,用這種方法,無論怎麼做,都已經在對原View進行侵入式的變動,這種方法不到萬不得已,不想用,因為一不小心改出連鎖反應的bug,導致原來的某些特性都受到影響,得不償失。

但是谷歌ViewPager提供了一個另外的思路,將內部View對象,以及view的相關參數通過接口的形式開放給外界,讓編程者可以不再需要關心原本View的內部實現,而直接專心做自己的特效,符合編程的開閉法則,即保證了原代碼的安全,又讓新的特效代碼與原View代碼沒有直接關聯。這是一種優雅,安全又高效的編程方式!

結語

至此,ViewPager部分結束。做出這個效果的基本思路和詳細過程都已經呈上。

再次給出Demo地址:https://github.com/18598925736/StudyTabLayout/tree/hank_v1

此Demo不僅僅是針對ViewPager的滑動特效,還包含了TabLayout 呈現效果的完全自定義。至於TabLayout如何隨心所欲的操縱,下一篇文章將會詳解。先預告一個最終效果圖, 文章會盡快出爐。

手把手講解ViewPager翻頁特效:關鍵代碼


分享到:


相關文章: