TimeInterpolator 是整個動畫插值器的最頂層接口,只有一個方法,此處列出代碼文件全文:html
package android.animation; /** * A time interpolator defines the rate of change of an animation. This allows animations * to have non-linear motion, such as acceleration and deceleration. */ public interface TimeInterpolator { /** * Maps a value representing the elapsed fraction of an animation to a value that represents * the interpolated fraction. This interpolated value is then multiplied by the change in * value of an animation to derive the animated value at the current elapsed animation time. * * @param input A value between 0 and 1.0 indicating our current point * in the animation where 0 represents the start and 1.0 represents * the end * @return The interpolation value. This value can be more than 1.0 for * interpolators which overshoot their targets, or less than 0 for * interpolators that undershoot their targets. */ float getInterpolation(float input); }
從註釋來看,它的做用是「定義動畫改變的速率,使得動畫不必定要勻速改變,能夠加速、減速。」
真實世界不老是勻速運轉的,若是咱們針對不一樣的場景採用合適的插值器,動畫的表現會天然好看,從而爲 App 增添色彩 ( ˇˍˇ )java
問題是,插值器是怎麼辦到的?繼續看註釋。android
插值器用一個 0~1.0 範圍的浮點數表示當前動畫播放的進度,0 表明開始播放,1.0 表明播放結束。經過 getInterpolation
把當前進度映射成另外一個值。動畫參照的時間由此被「篡改」,動畫的速度由此被改變。算法
所以,咱們能夠這樣理解插值器:把處於某個區間(有起點值和終點值)的一個值,按照某種算法,映射爲另外一個值。
Interpolator 漢語解釋有兩種:(1)【數學】內插器;分數計算器;(2)篡改者。印證了咱們的理解。api
接下來要思考的問題是,getInterpolation
是怎麼被調用到的?要回答這個問題,咱們必須回到 ValueAnimator
的源碼:app
AnimationHandler 是 ValueAnimator 定義的一個靜態內部類,它實現了一個 runnable,在內部維護一個計時循環(和 Choreographer
有關 TODO),從而產生計時脈衝(timing pulse),動畫之因此能「動」,就是計時脈衝在起做用,可認爲是動畫的「心臟」,功能相似於單片機的晶振。less
程序內全部動畫共享同一個脈衝,使全部動畫共享一個時間,以保證同步。每次脈衝發生時,每個動畫都會根據當前時間(對應@input)和 TimeInterpolator(對應 getInterpolation方法),計算出另外一時間(對應 @return)。如下是函數調用棧(不徹底):函數
// 內部維護一個 runnable,`Choreographer` 應該是維護計時循環的核心類,暫不深究了 TODO; run(); // 總之這個函數會被定時調用到,它遍歷全部的動畫,決定把某個動畫放入等待隊列,仍是從等待隊列中取出來執行; doAnimationFrame(long mChoreographer.getFrameTime()); // 若是某個動畫處於激活狀態,則這個函數會被調用到; anim.doAnimationFrame(long frameTime) // 而後調用到這個函數,上述函數調用中的 frameTime 被轉換成了 currentTime,表示動畫的當前時間; animationFrame(long currentTime); // 這個算式很簡單,根據動畫時長、當前時間、開始時間,算出動畫的播放進度,一個 0~1.0 範圍的浮點數; float fraction = mDuration > 0 ? (float)(currentTime - mStartTime) / mDuration : 1f; // 接下來的這個函數調用就很關鍵了,它的入口參數是動畫的播放進度; animateValue(float fraction); // 其一:經過 Interpolator 篡改播放進度; fraction = mInterpolator.getInterpolation(float fraction); // 其二:經過 TypeEvaluator 計算動畫過程值,PropertyValuesHolder 是處理計算的核心類 TODO; mValues[i].calculateValue(fraction); // 其三:回調監聽器,發出動畫值改變的通知; mUpdateListeners.get(i).onAnimationUpdate(this);
Interpolator.getInterpolation(float) 篡改了播放進度;
TypeEvaluator 拿着被篡改的進度計算當前的動畫過程值 evaluate(float fraction, Object startValue, Object endValue)
。工具
這樣,動畫就能夠忽快忽慢,或者全程加速,或者全程減速,或者是某種奇特的時間曲線。學習
TimeInterpolator 畢竟只是一個接口,沒有任何具體實現,因此播放進度究竟是如何被篡改的呢?請看它的「徒子徒孫」:
public interface TimeInterpolator {} public interface Interpolator extends TimeInterpolator {} abstract public class BaseInterpolator implements Interpolator {} // 直接繼承自 BaseInterpolator 的子類有: AccelerateDecelerateInterpolator, AccelerateInterpolator, AnticipateInterpolator, AnticipateOvershootInterpolator, BounceInterpolator, CycleInterpolator, DecelerateInterpolator, LinearInterpolator, OvershootInterpolator, PathInterpolator
(http://grepcode.com/file/repository.grep...
這是默認的插值器,若是 setInterpolator(null) 則是線性插值器。(查閱API說明)
它的行爲:開始和結尾減速、中間加速。(PS:和繩命的軌跡類似(繩命的幼年和老年、繩命的青年),這是成爲默認插值器的理由,一個猜測,多是對的。)
它的插值方法:
public float getInterpolation(float input) { return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f; }
什麼?你說抽象?不要緊,上圖,插值方法對應的圖形:
紅線是我特地標註的,在 [0, 1] 範圍內,開頭和結尾斜率小,中間斜率大。也就是說,兩頭慢,中間快。
CycleInterpolator 的插值方法:
public float getInterpolation(float input) { return (float)(Math.sin(2 * mCycles * Math.PI * input)); }
CycleInterpolator mCycles=1 時的圖形:
被篡改後的播放進度爲負數是怎麼回事?須要回到 getInterpolation(float) 方法,查看它對返回值的解釋:
@return The interpolation value. This value can be more than 1.0 for interpolators which overshoot their targets, or less than 0 for interpolators that undershoot their targets.
[0, 1.0] 是未被篡改前的動畫播放進度範圍(即入口參數的範圍),至於被篡改後的值,超過 1 被稱爲「過沖」,小於 0 被稱爲「下衝」。
過沖和下衝目前我理解的也不是很清楚(TODO),因此仍是看 GIF 圖吧:
CycleInterpolator 的 GIF 效果圖:
這裏只列出了兩個插值器,還有不少不少,理解這些插值器的最好辦法是觀看它們的運行效果,修改參數再次觀看運行效果。 ApiDemos 包含這樣的代碼:
ApiDemos/app/src/main/java/com/example/android/apis/view/Animation3.java
1. 插值法、內插法、內推法、插入法 2. 插入、插入物 3. 竄改
~by central difference 中差插值法 ~by continued fractions 用連分式的插值法 ~by convergents 收斂插值法 ~by propotionaI parts 比例插值法 ~error 內插偏差 ~error-filter 內插偏差濾波器 ~factor 內插因子 ~formula 插值公式 ~functions 插值函數 ~line 內插行 ~method 內插法,插入法 ~models 插值模型 ~of contours 等高線內插 ~of gravity 重力內插 ~oscillator 內插振盪器 ~polynomial 插值多項式 ~property 插入性質 ~series 插值級數 ~set 插入集[合] ~table 內插表 ~technique 插入法,間插法 ~theory 插值理論
來源:英漢科技大詞庫·第二卷 E-M
更多用法請查閱知乎問題 如何高效地使用搜索引擎?
https://m.oschina.net/blog/137391
http://blog.kainaodong.com/?p=42
http://www.cnblogs.com/mengdd/p/3346003....
當代生活太慢了!必須提速了!縱身一躍!旁友們,以光速投身在星辰大海,必須讓靈魂數位化了!生活太緩慢簡直是犯罪,你今天洗了幾個碗。2014-03-29
人,不要鬧騰,躺着最好。存在的真諦是慢,讓生活慢下來。和烏龜學習!(三姨夫生活感悟 2014-07-26
曆法徹底是個騙局,純粹是統治階級爲了mindfuck人們的工具,個體對時間流逝的感知不一樣,怎麼能同樣算呢,好比老張時間過的慢,今年只有20歲,但按公曆算已經45了,不公平!小劉12歲按公曆算已經32了,這樣男的放進學校能放心嗎?建議取消曆法,讓生活模糊起來!就分之前和之後,保持時間的連續性 2015-11-19
星期日下午三點半,你忽然決定今後刻起比別人慢一秒,太棒了!在全部精確的嚴絲合縫的必須的無可置疑的社會主義生活方式中猛的後撤,過一種慢一步的生活,你成功了,一些不知所措在你上方集中,你陌生化成功了,生活第一次輸了 2016-01-17
版權聲明:《Android Animation Interpolator - Android 動畫插值器源碼筆記》由 WeiYi.Li 在 2016年01月31日寫做。著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。
文章連接:http://li2.me/2016/01/android-animation-...