前言:
上一篇文章我向大家介紹了屬性動畫里面的一個基類ValueAnimator的使用,與功能的敘述,這一邊就針對里面的比較重要的兩點知識展開深入一點的敘述,就是Interpolator(插值器)與Evaluator估值器的講解,其中的估值器,在以前的補間動畫是沒引入的,后面的屬性動畫引進(jìn),屬性動畫中,這兩種自定義之后可以實現(xiàn)比較多的效果,希望此篇文章對各位小猿們有一定的幫助,那樣本人也是開森的。
分析:
一、Interpolator(插值器):
1.概念:直譯過來就是插補器,也譯作插值器,直接控制動畫的變化速率,這涉及到變化率概念,形象點說就是加速度,可以簡單理解為變化的快慢。從上面的繼承關(guān)系可以清晰的看出來,Interpolator是一個接口,并未提供插值邏輯的具體實現(xiàn),它的非直接子類有很多;
2.先上源碼,瞅瞅先:
public class LinearInterpolator extends Interpolator {
public LinearInterpolator() {
}
public LinearInterpolator(Context context, AttributeSet attrs) {
}
public float getInterpolation(float input) {
return input;
}
}
LinearInterpolator實現(xiàn)了Interpolator接口;而Interpolator接口則直接繼承自TimeInterpolator,而且并沒有添加任何其它的方法。其實我們看get方法里面,什么都沒有操作,輸入的什么輸出的就是什么,這不正是勻速運動的思想的嗎。很簡單吧!
那我們來看看TimeInterpolator接口都有哪些函數(shù)吧:
/**
* 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);
}
這里是TimeInterpolator的代碼,它里面只有一個函數(shù)float getInterpolation(float input);我們來講講這個函數(shù)是干什么的。
參數(shù)input: input參數(shù)是一個float類型,它取值范圍是0到1,表示當(dāng)前動畫的進(jìn)度,取0時表示動畫剛開始,取1時表示動畫結(jié)束,取0.5時表示動畫中間的位置,其它類推。
返回值: 表示當(dāng)前實際想要顯示的進(jìn)度。取值可以超過1也可以小于0,超過1表示已經(jīng)超過目標(biāo)值,小于0表示小于開始位置。 也正是因為每種插值器返回值不同才形成了不同運動效果的動畫
對于input參數(shù),它表示的是當(dāng)前動畫的進(jìn)度,勻速增加的。什么叫動畫的進(jìn)度,動畫的進(jìn)度就是動畫在時間上的進(jìn)度,與我們的任何設(shè)置無關(guān),隨著時間的增長,動畫的進(jìn)度自然的增加,從0到1;input參數(shù)相當(dāng)于時間的概念,我們通過setDuration()指定了動畫的時長,在這個時間范圍內(nèi),動畫進(jìn)度肯定是一點點增加的;就相當(dāng)于我們播放一首歌,這首歌的進(jìn)度是從0到1是一樣的。
而返回值則表示動畫的數(shù)值進(jìn)度,它的對應(yīng)的數(shù)值范圍是我們通過ofInt(),ofFloat()來指定的,這個返回值就表示當(dāng)前時間所對應(yīng)的數(shù)值的進(jìn)度
3.自定義(看到這里是不是童鞋自己都可以自定義一個簡單的插值器)
其實Android安卓提供的插值器已經(jīng)非常全了。我個人感覺沒有必要再去自定義插值器。當(dāng)然既然我們都清楚原理了,那么就自定義一個自己的插值器試一下。 如下:
public class MyInterploator implements TimeInterpolator {
@Override
public float getInterpolation(float input) {
return 1-input;
}
}
自定義插值器注意2點:1.繼承TimeInterpolator 2.返回當(dāng)前的顯示進(jìn)度。這里我們將進(jìn)度反轉(zhuǎn)過來,當(dāng)傳0的時候,我們讓它數(shù)值進(jìn)度在完成的位置,當(dāng)完成的時候,我們讓它在開始的位置。跟家復(fù)雜的可以參考自帶的其他插值器。
4.系統(tǒng)提供的一些插值器列表(感興趣的童鞋自己試試):
1:AccelerateDecelerateInterpolator 加速減速插補器(先慢后快再慢)
2:AccelerateInterpolator 加速插補器(先慢后快)
3:AnticipateInterpolator 向前插補器(先往回跑一點,再加速向前跑)
4:AnticipateOvershootInterpolator 向前向后插補器(先往回跑一點,再向后跑一點,再回到終點)
5:BounceInterpolator 反彈插補器(在動畫結(jié)束的時候回彈幾下,如果是豎直向下運動的話,就是玻璃球下掉彈幾下的效果)
6:CycleInterpolator 循環(huán)插補器(按指定的路徑以指定時間(或者是偏移量)的1/4、變速地執(zhí)行一遍,再按指定的軌跡的相反反向走1/2的時間,再按指定的路徑方向走完剩余的1/4的時間,最后回到原點。假如:默認(rèn)是讓a從原點往東跑100米。它會先往東跑100米,然后往西跑200米,再往東跑100米回到原點??稍诖a中指定循環(huán)的次數(shù))
7:DecelerateInterpolator 減速插補器(先快后慢)
8:LinearInterpolator 直線插補器(勻速)
9:OvershootInterpolator 超出插補器(向前跑直到越界一點后,再往回跑)
10:FastOutLinearInInterpolator MaterialDesign基于貝塞爾曲線的插補器 效果:依次 慢慢快
11:FastOutSlowInInterpolator MaterialDesign基于貝塞爾曲線的插補器 效果:依次 慢快慢
12:LinearOutSlowInInterpolator MaterialDesign基于貝塞爾曲線的插補器 效果:依次 快慢慢
二、Evaluator(估值器):
1.概念:TypeEvaluator估值器,他的作用是根據(jù)當(dāng)期屬性的百分比來計算改變后的屬性值。Evaluator其實就是一個轉(zhuǎn)換器,他能把小數(shù)進(jìn)度轉(zhuǎn)換成對應(yīng)的數(shù)值位置。
先上一個圖:(比較利于吃雞)
這幅圖講述了從定義動畫的數(shù)字區(qū)間到通過AnimatorUpdateListener中得到當(dāng)前動畫所對應(yīng)數(shù)值的整個過程。下面我們對這四個步驟具體講解一下:
(1)、ofInt(0,400)表示指定動畫的數(shù)字區(qū)間,是從0運動到400;
(2)、加速器:上面我們講了,在動畫開始后,通過加速器會返回當(dāng)前動畫進(jìn)度所對應(yīng)的數(shù)字進(jìn)度,但這個數(shù)字進(jìn)度是百分制的,以小數(shù)表示,如0.2
(3)、Evaluator:我們知道我們通過監(jiān)聽器拿到的是當(dāng)前動畫所對應(yīng)的具體數(shù)值,而不是百分制的進(jìn)度。那么就必須有一個地方會根據(jù)當(dāng)前的數(shù)字進(jìn)度,將其轉(zhuǎn)化為對應(yīng)的數(shù)值,這個地方就是Evaluator;Evaluator就是將從加速器返回的數(shù)字進(jìn)度轉(zhuǎn)成對應(yīng)的數(shù)字值。所以上部分中,我們講到的公式:
當(dāng)前的值 = 100 + (400 - 100)* 顯示進(jìn)度
(4)、監(jiān)聽器:我們通過在AnimatorUpdateListener監(jiān)聽器使用animation.getAnimatedValue()函數(shù)拿到Evaluator中返回的數(shù)字值。
2.先上源碼,瞅瞅先:
public class IntEvaluator implements TypeEvaluator<Integer> {
/**
* This function returns the result of linearly interpolating the start and end values, with
* <code>fraction</code> representing the proportion between the start and end values. The
* calculation is a simple parametric calculation: <code>result = x0 + t * (v1 - v0)</code>,
* where <code>x0</code> is <code>startValue</code>, <code>x1</code> is <code>endValue</code>,
* and <code>t</code> is <code>fraction</code>.
*
* @param fraction The fraction from the starting to the ending values
* @param startValue The start value; should be of type <code>int</code> or
* <code>Integer</code>
* @param endValue The end value; should be of type <code>int</code> or <code>Integer</code>
* @return A linear interpolation between the start and end values, given the
* <code>fraction</code> parameter.
*/
public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
int startInt = startValue;
return (int)(startInt + fraction * (endValue - startInt));
}
}
首先IntEvaluator繼承了我們的TypeEvaluator估值器。因為是IntEvaluator所以指定的泛型類型為Integer,同時里面實現(xiàn)了一個方法,這個方法的參數(shù)的含義
fraction:估值小數(shù)(就是加速器中的返回值,表示當(dāng)前動畫的數(shù)值進(jìn)度,百分制的小數(shù)表示。)
startValue: 動畫開始的值
startValue: 動畫結(jié)束的值
返回值: 就是我們在AnimatorUpdateListener監(jiān)聽中得到具體運動的值。
我們可以看到返回值的運算公式正是我們在插值器中所提到的公式
當(dāng)前的值= 開始的值 + 當(dāng)前的進(jìn)度 * (結(jié)束的進(jìn)度 - 開始的進(jìn)度)
我們用圖片中的例子如果加載器為勻速加速器,動畫時長為2s,在1s時(也就是動畫運動到一半的時候),這三個參數(shù)依次為0.5,100,400,此時在監(jiān)聽中得到的結(jié)果為:
當(dāng)前的值 = 100 + (400 - 100)* 0.5 //結(jié)果為250
3.自定義:
理解了估值器以后我們就可以試著自定義自己的估值器。只需要實現(xiàn)TypeEvaluator接口,并實現(xiàn)里面唯一的一個方法即可。
下面提供2種簡單的自定義估值器:
(1)、簡單實現(xiàn)MyEvalutor
public class MyEvaluator implements TypeEvaluator<Integer> {
@Override
public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
int startInt = startValue;
return (int)(200+startInt + fraction * (endValue - startInt));
}
}

(2)、實現(xiàn)倒序輸出實例
public class ReverseEvaluator implements TypeEvaluator<Integer> {
@Override
public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
int startInt = startValue;
return (int) (endValue - fraction * (endValue - startInt));
}
}

其中 fraction * (endValue - startInt)表示動畫實際運動的距離,我們用endValue減去實際運動的距離就表示隨著運動距離的增加,離終點越來越遠(yuǎn),這也就實現(xiàn)了從終點出發(fā),最終運動到起點的效果了。
總結(jié):
在加速器中,我們可以通過自定義加速器的返回的數(shù)值進(jìn)度來改變返回數(shù)值的位置。比如上面我們實現(xiàn)的倒序動畫
在Evaluator中,我們又可以通過改變進(jìn)度值所對應(yīng)的具體數(shù)字來改變數(shù)值的位置。 所以可以通過重寫加速器改變數(shù)值進(jìn)度來改變數(shù)值位置,也可以通過改變Evaluator中進(jìn)度所對應(yīng)的數(shù)值來改變數(shù)值位置。雖然2者都可以改變位置。但是插值器(加速器)是根據(jù)運動是時間來決定當(dāng)前進(jìn)度的百分比。估值器是根據(jù)加速器的百分比來計算具體的數(shù)值。作用相同,職責(zé)不同。