原理分析:
首先說Animation(android.view.animation.Animation)對象,無論是用純java代碼構建Animation對象,還是通過xml文件定義Animation,其實最終的結果都是
Animation a = new AlphaAnimation();Animation s = new ScaleAnimation();Animation r = new RotateAnimation();Animation t = new TranslateAnimation();
分別是透明度,縮放,旋轉,位移四種動畫效果。
而我們使用的時候,一般是用這樣的形式:
那麼就來看看View中的startAnimation()方法:
先是調用View.setAnimation(Animation)方法給自己設置一個Animation對象,這個對象是View類中的一個名爲mCurrentAnimation的成員變量:
然後它調用invalidate()來重繪自己。我想,既然setAnimation()了,那麼它要用的時候,肯定要getAnimation(),找到這個方法在哪裏調用就好了。於是通過搜索,在View.draw(Canvas, ViewGroup, long)方法中發現了它的調用,代碼片段如下:
其中調用了View.drawAnimation()方法:
其中調用了Animation.getTransformation()方法:
該方法先將參數currentTime處理成一個float表示當前動畫進度,比如說,一個2000ms的動畫,已經執行了1000ms了,那麼進度就是0.5或者說50%。然後將進度值傳入插值器(Interpolator)得到新的進度值,前者是均勻的,隨着時間是一個直線的線性關係,而通過插值器計算後得到的是一個曲線的關係。然後將新的進度值和Transformation對象傳入applyTranformation()方法中:
Animation的applyTransformation()方法是空實現:
而具體實現它的是Animation的四個子類,而該方法正是真正的處理動畫變化的過程。分別看下四個子類的applyTransformation()的實現:
其中一個代碼如下:
可見applyTransformation()方法就是動畫具體的實現,系統會以一個比較高的頻率來調用這個方法,一般情況下60FPS,是一個非常流暢的畫面了,也就是16ms,爲了驗證這一點,我在applyTransformation方法中加入計算時間間隔並打印的代碼進行驗證,代碼如下:
自定義:
調用:
打印:
封裝一個InterpolatedTime(float time)函數,在applyTransformation調用:
Log:
右側是“手動”計算出來的時間差,有一定的波動,但大致上是16-17ms的樣子,左側是日誌打印的時間,時間非常規則的相差20ms。
總結:
於是,根據以上的結果,可以得出以下內容:
1.首先證明了一點,Animation.applyTransformation()方法,是動畫具體的調用方法,我們可以覆寫這個方法,快速的製作自己的動畫。
2.另一點,爲什麼是16ms左右調用這個方法呢?是誰來控制這個頻率的?
關於第二點,要分析:Choreographer!