Shimmer是啥玩意
Shimmer是可以為你的APP中的任何檢視新增”一閃一閃”的效果。最初源自於facebook的 Paper 應用。傳送門:GitHub – facebook/Shimmer: An easy way to add a simple
效果圖
Shimmer原始碼主要分為以下三個檔案:
- FBShimmering : 一個協議,主要用來封裝一些常用的屬性,比如:速度、透明度、持續時間等。
- FBShimmeringView : 實現FBShimmering協議,主要用來修改其圖層類為FBShimmeringLayer,提供類似代理功能,並對外提供View。
- FBShimmeringLayer : 實現了FBShimmering協議,是實現整個動畫效果的核心部分,我們將在具體分析階段詳解。
原始碼分析
FBShimmering
略過,因為太簡單
FBShimmeringView
難點一:
解析:
通過重新實現layerClass方法來修改FBShimmeringView的關聯圖層,對FBShimmeringView的操作就會由FBShimmeringLayer來實現。
難點二:
解析:
通過巨集定義的方式實現FBShimmering協議屬性的Get和Set方法。
FBShimmeringLayer
難點一:
解析:
這裡引用了UIKit的私有方法UIAnimationDragCoefficient,這裡先通過UIKIT_EXTERN的方式將其引入進來。該方法返回一個”拖拽係數”,正常情況下,這個值為1。同時這個方法對應著我們模擬器的”Slow Animations”選項,當我們開啟這個選項的時候, 他的值變成了10,也就是說我們執行的動畫比原來慢了10倍。
難點二:
解析:
清除蒙版,在這之間需要禁用圖層行為。
難點三 :
解析:
為蒙版建立顏色陣列,這裡需要注意的是蒙版所對應的 CALayer所能表現出來的屬性只能是透明度。縱使蒙版是其他顏色或是圖片,也不能表現出來想要的色彩效果。所以換成其他的顏色陣列效果也是一樣的。
難點四:
解析:
主要用來初始化蒙版。先根據閃爍的方向計算出長度,如果長度為0直接返回。在根據長度分別計算出蒙版的長度、蒙版移動的距離。在根據蒙版的長度和移動距離計算出蒙版圖層的startPoint以及endPoint。這裡將anchorPoint設定為(0.0),主要是方便圖層的position計算。這裡不要太糾結於extraDistance、fullShimmerLength、travelDistance變數的計算,比如說為什麼是*3和*2,你也可以設定其他的值,但是動畫效果就沒原先的好,你就姑且當他是一個魔法引數。
難點五:
解析:
這個方法也是最核心的部分。整個過程分為兩個步驟:
1:暫停閃動的時候伴隨一個淡入的動畫。
2:開始閃動的時候一個淡出的動畫、接著跟隨不斷閃動的動畫。
第一階段中先判斷是否禁用圖層行為,如果禁用了就直接返回。如果沒有禁用,則通過kvc的方式先獲取閃動動畫。判斷閃動動畫是否為空,若不為空,則計算閃動動畫總共執行了多少時間。並通過總的時間和每次執行的時間取模,得當當前閃動的時間偏移,然後通過這個時間偏移計算出這次閃動結束時的時間,而這個時間用來構造淡入動畫的beginTime,最後將這個淡入動畫加入這個圖層。
第二階段中先判斷是否支援淡出動畫,如果支援就構建一個淡出動畫並加入圖層,如果沒有就設定透明屬性為0,並移除所有動畫。然後通過KVC獲取閃動動畫,並判斷是否為空,如果不為空則呼叫shimmer_slide_repeat方法主要將其repeatCount屬性設定為沒有限制。如果為空,則初始化一個閃動動畫。最後將其加入到圖層中。
以下是我理的思路圖:
這裡我還想解釋下MASK(蒙版)的概念:
蒙版的作用是利用Alpha通道使View的內容有部分展示功能,我們能通過mask去給內容的特定區域增加特定的效果。公式如下:
展示的alpha = content的Alpha * maskLayer的Alpah
很明白,如果maskLayer的alpha是0,那麼相對應的content部分內容就會被遮擋。如果maskLayer的alpha是1,那麼content內容便全部展示出來。
如果理解有錯誤的地方,歡迎大家可以指出來,一起探討。
打賞支援我寫出更多好文章,謝謝!
打賞作者
打賞支援我寫出更多好文章,謝謝!
任選一種支付方式