屬性動畫系統是一個健壯的架構,它幾乎可以允許把任何對象變成動畫。可以根據時間的推移來改變任何對象的屬性來定義一個動畫,而不用關心該對象是否要繪製在螢幕上。屬性動畫是在指定的時間長度上改變一個屬性(對象中的一個成員欄位)的值。要讓某些對象變成動畫,就要給該對象指定想要的動畫屬性,如果對象在螢幕上的位置、動畫的停留時間以及動畫之間的值等。
屬性動畫系統可以定義以下動畫特性:
1. 期間(Duration):指定動畫的期間。預設長度是300毫秒。
2. 時間插值(Time interpolation):這個值能夠做為計算當前動畫已耗用時間的函數的屬性值來指定,它決定動畫的變化頻率。
3. 重複次數和行為(Repeat count and behavior)
這個屬效能夠指定在動畫結束時是否重新播放動畫,以及重複播放的次數。還能夠指定動畫是否能夠反向回播,如果設定了反向回播,那麼動畫就會先向前再向後,重複播放,直到達到播放次數。
4. 動畫集合(Animator sets):你能夠把動畫組織到一個邏輯集合中,然後或者同時、或者順序的、或者延遲播放它們。
5. 幀重新整理延遲(Frame refresh delay):你能夠指定動畫幀的重新整理頻率。預設是每10秒中重新整理一次,但是應用程式最終的重新整理幀的速度依賴與系統的繁忙程度以及系統能夠提供的底層定時器的反應速度。
屬性動畫是如何工作的
首先,讓我們用一個簡單的例子來看一下動畫的工作方式。圖1繪製了一個假想的動畫對象,它用x屬性來表示其在螢幕上的水平位置。動畫的期間被設定為40毫秒,並且移動的距離是40個像素。每10毫秒,是預設的幀重新整理頻率,即每10毫秒對象水平移動10個像素。在40毫秒結束時,動畫停止,並且動畫要停留在水平40像素點的位置上。這是一個線性插值的動畫樣本,意味著動畫勻速運動。
圖1.線性動畫樣本
還可以指定非線性差值的動畫。圖2假設了一個加速開始、減速結束的動畫對象,該對象依然在40毫秒內移動了40個像素,但是非線性。在開始的時候,這個動畫加速運動到一半的位置,然後開始減速運動直到動畫結束。2所示,對象啟動並執行距離在開始和結束階段要比中間部分短。
圖2.非線性動畫的樣本
接下來讓我們更詳細的瞭解屬性動畫系統的重要組件是如何計算所示動畫。圖3繪製了主類和其他類是如何一起工作的。
圖3.動畫的計算方式
ValueAnimator對象保持著動畫的時間軌跡,如動畫的已耗用時間,以及動畫屬性的當前值。
ValueAnimator類封裝了一個TimeInterpolator類,這個類定義了動畫的差值,和一個TypeEvaluator類,這個類定義動畫屬性值的計算方式。例如,在圖2中TimeInterpolator對象使用AccelerateDecelerateInterpolator定義,TypeEvaluator使用了IntEvaluator定義。
要啟動一個動畫,就要建立一個ValueAnimator對象,並且要給該對象設定想要的動畫的屬性的開始和結束值,以及動畫的期間。在調用start()方法開始動畫的時候,整個動畫期間,ValueAnimator對象會根據動畫的期間和已經執行的時間,在0和1之間,計算一個elapsed fraction(過去係數)。這個係數代表了動畫已經完成的百分比,0意味著0%、1意味著100%。例如,圖1中,在t = 10毫秒處的過去係數是0.25,因為總的期間是t = 40毫秒。
當ValueAnimator對象完成過去係數的計算時,它會調用當前設定的TimeInterpolator對象,來計算一個差值係數(interpolated fraction)。差值係數(interpolated fraction)把過去係數(elapsed fraction)映射到一個新的考慮設定時間差值的係數。例如,在圖2中,因為動畫是慢慢的加速,因此在t=10毫秒時,差值係數大約是0.15,它比過去係數(elapsed fraction)0.25要小。在圖1中,差值係數(interpolated fraction)與過去係數(elapsed fraction)始終相同。
在計算差值係數(interpolated fraction)時,ValueAnimator對象會調用相應的TypeEvaluator對象,基於差值係數、動畫的開始值、結束值,來計算動畫的屬性值。例如,在圖2中,在t = 10毫秒處,差值係數是0.15,因此在此時的屬性值應該是0.15*(40 – 0)= 6。
作者:FireOfStar