在使用動畫Animation或者AnimationSet的時候,有一個interpolator插補器的屬性。可以用來設定動畫運動時的速率。那麼,插補器是怎麼實現一個動畫的速率改變的呢?
在講這些之前,我想先補充說點,動畫插補器目前都只是對動畫執行過程的時間進行修飾,並沒有對軌跡進行修飾。因為所有的插補器都是實現了Interpolator這個介面,而Interpolator又是繼承自一個叫做TimeInterpolator的介面(從3.0開始,增加了TimeInterpolator這個介面,並把原先的Interpolator介面的抽象方法移到了其中,3.0後的Interpolator介面也就什麼也沒做,只是對父類改了個名字,達到向下相容)。
插補器的原理就是通過改變實際執行動畫的時間點,提前/順延強制預設的時間點來達到加速/減速的效果。(所以,有些朋友可能想通過它來實現一些特定的軌跡,這並不能達到目的。至少目前的api是不支援的。最多通過設定負時間/大於1的時間比,來使控制項按設定的動畫軌跡反方向/超出改變一點軌跡。)
在Interpolator的實作類別裡面,都實現了一個float getInterpolator(float input)的方法。傳入參數是正常執行動畫的時間點,傳回值是使用者真正想要它執行的時間點。傳入參數是0~1,傳回值一般也是0~1。(0~1)表示整段動畫的過程。中間的0.2、0.3等小數表示在整個動畫(原本是勻速的)中的位置,其實就是一個比值。如果傳回值是負數,會沿著相反的方向執行。(如果是alpha值,返回負數會有點問題,因為alpha值比較特殊,本身只能是0~1,並不是一個迴圈的周期,如果取了負值,這就很難確定了,要看android是怎麼計算alpha值的。)如果返回的是大於1,會超出正方向執行。同樣,如果是alpha值,也存在不確定的效果。
簡單點解釋這個方法,就是當要執行input的時間時,給它另外一個時間,讓系統執行另外一個時間的效果。
比如:
在加速插補器裡面,這個重載方法是這樣的:
[java]
public float getInterpolation(float input) {
if (mFactor == 1.0f) {
return input * input;
} else {
return (float)Math.pow(input, mDoubleFactor);
}
}
public float getInterpolation(float input) {
if (mFactor == 1.0f) {
return input * input;
} else {
return (float)Math.pow(input, mDoubleFactor);
}
}mFactor其實一直都是1,因為設定檔並沒有提供設定其它值的入口,預設會是1。mDoubleFactor是2,由此可見,這個方法其實就是個x^2的曲線。當input=0.3時,傳回值=0.09,假如這個動畫的總時間長度是1秒,也就是說,在0.3秒的時候只是執行0.09秒時候的效果。這樣說可能還有點難理解。
其實這個速度和x^2這條拋物線的斜率的變化是有關的,和斜率的變動率是正比關係。比如,上面這個加速插補器的曲線就如:
紅色的那條是正常的時間-實際時間變化曲線:g(x)=x;實際時間是按照正常時間勻速變化的,斜率是常數1.而拋物線在[0,1]時,斜率先是0,再慢慢增加的。也就是在0時,執行的時間是0,在0.1時,執行的時間(位置)依然是接近於0的時間點(執行的位置)。執行的時間一直比正常該執行的時間點遲。但是執行的時間變化的增量也一直在變,而且越變越快,也就是斜率一直在變大,這導致了感官上看到了一個加速的過程。它起步的速度是一樣的,但是它把原本該執行的時間提前執行/或者延遲執行,由此產生速度不一致。
另附系統提供的其它幾個插補器的曲線圖:
1.AccelerateDecelerateInterpolator 加速減速插補器
取值是[0,1],可見,從原點開始,斜率是0,先圓滑地慢慢增大,再慢慢減小,最後傳回值還是1。這就是一個先加速再減速的效果。而且整個過程是平滑變化的。這也是數學的奧妙啊。
2.DecelerateInterpolator 減速插補器
明顯,雖然斜率一直是大過正常值(因為開始時執行較快,後來才慢慢迴歸正常時間,但直到最後一刻才回到),但斜率一直在減小,是一個減速的過程。
3.AnticipateInterpolator 向前插補器
這是一條符合g(x)=3x^3-2x^2的曲線。前面2/3秒之前(假設整個過程是1秒),傳回值是負數。如果這是一個直線運動的動畫,這段時間會向設定的相反的方向運動一點,而且速度顯得稍緩(反方向先加速再減速)。這之後以一個較快速度跑到終點(大概0.7秒時會回到原點)。
4.AnticipateOvershootInterpolator 向前向後插補器
這是3條曲線合并起來的圖,我們只需要較深色的那條x軸上[0,0.5)和稍淺那條[0.5,1]這兩段就可以。可以看到,前面一點時間有一段負數的傳回值,而後面有一段大於1的傳回值,這就有了向前向後的效果。
5.OvershootInterpolator 超出插補器
開始時有個加速過程,超出邊界後,速度慢慢降下來,最後返回到終點。
總之,斜率大於1速度就比正常快,小於1比正常慢,小於0往反方向運動。斜率變大就加速,斜率變小就減速(但速度不一定比正常慢)。
還有迴圈插補器CycleInterpolator 和反彈插補器BounceInterpolator,基本原理都一樣,只是函數圖象需要做更細的分段處理,這裡就不做介紹了。