這次來實現(xiàn)RecyclerView視差動畫,先來看下效果:

那要怎么實現(xiàn)呢?我這里是通過ImageView設(shè)置Matrix實現(xiàn),有更好的辦法歡迎留言告知。
那么Matrix是什么呢?我這里就簡單的說一下,如果想詳細了解的話,請自行搜索查看。

matrix是一個3*3的矩陣,MSCALE_X、MSCALE_Y是來控制綻放的,MSKEW_X,MSKEY_Y是來控制錯切的,MTRANS_X、MTRANS_Y是來控制位移的,MPERSP_0、MPERSP_1、MPERSP_2是來控制透視的,MSCALE_X、MSCALE_Y、MSKEW_X、MSKEW_Y是用來控制旋轉(zhuǎn)的。
那我們要怎么對矩陣操作,可能大家都把線性代數(shù)還回給老師了,就算沒還,算起來也麻煩,所以谷歌給我們提供了方便的方法,分別是preRotate()、setRotate()、postRotate,代表的是左乘、設(shè)置和后乘。這之間的差別我就不詳細介紹了。視差效果主要用到了位移和縮放。
那這個效果的思路是怎樣?我們對效果進行拆分,其實發(fā)現(xiàn)每個圖片的效果都是一樣的,滾動后圖片也跟著移動,圖片從RecyclerView頂部到達RecyclerView底部剛好遍歷一整張圖片,頂部時,圖片也顯示頂部。到達底部時,圖片也顯示底部,如圖所示。


那我們可以先對這個效果進行分解,在沒有RecyclerView的時候,對ImageView進行圖片的縮放和移動。
首先為ImageView設(shè)置圖片,然后設(shè)置ScapeType為Matrix,然后根據(jù)圖片比例進行計算,縮放使圖片占滿ImageView,因為我們的圖片是要上下移動,所在我們在放大的時候要在CenterCrop的基礎(chǔ)上保證上下有一部分剩余,這樣才可以移動。并且圖片一開始位于ImageView的頂部。代碼如圖所示:

這里做的事件也很簡單,獲取drawable的原始寬高和ImageView的原始寬高,通過postScale()進行比較縮放,讓圖片占滿整個ImageView,這里ImageView的高度乘以1.1主要用于控制縮放后的圖片高度超過ImageView高度的1.1倍。當(dāng)置于recyclerview移動時,讓任何規(guī)格的圖片都可以上下移動,產(chǎn)生較明顯的視差效果。不然的話當(dāng)圖片控件寬高比相同(小于大于和控件圖片比例有關(guān))之類的情況下,會讓圖片上下無法移動。
那我們怎樣對內(nèi)部的圖片進行移動?可以通過postTranslationY()方法對圖片進行上下移動。看,是不是很簡單。


通過以上的步驟我們已經(jīng)可以控制圖片縮放到正確比例并上下移動,但是我們可以發(fā)現(xiàn)存在一個問題,圖片會被移出ImageView外面。我們可以進行糾正,當(dāng)圖片被移動到ImageView邊框外后,把圖片糾正回ImageView內(nèi)部。代碼如下:

這里主要通過mapRect()方法獲得通過變換后的圖片邊框位置,然后判斷是否超出ImageView的上下邊框,進行糾正,這樣就可能防止圖片移出ImageView的邊框。

現(xiàn)在我們已經(jīng)知道怎么圖片怎么通過Matrix進行移動。那實現(xiàn)RecyclerView的視差動畫肯定也難不倒聰明的你,只需要為RecyclerView添加addOnScrollListener()監(jiān)聽,當(dāng)RecyclerView滾動時,根據(jù)每個Item距離RecyclerView頂部的距離移動對應(yīng)的比例。這樣,我們就實現(xiàn)了我們的視差效果。