Interpolator的使用
在Android中使用屬性動畫時可以設定插值器,系統為我們提供了幾種已經實作了的插值器類。
分别為:
- LinearInterpolator 勻速直線運動
- AccelerateDecelerateInterpolator 中間快兩頭滿
- AccelerateInterpolator 開始慢然後快
- AnticipateInterpolator 開始的時候向後然後向前甩
- AnticipateOvershootInterpolator 開始的時候向後然後向前甩一定值後傳回最後的值
- BounceInterpolator 動畫結束的時候彈起
- CycleInterpolator 動畫循環播放特定的次數,速率改變沿着正弦曲線
- DecelerateInterpolator 在動畫開始的地方快然後慢
- OvershootInterpolator 向前甩一定值後再回到原來位置
源碼刨析
LinearInterpolator
public class LinearInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {
public LinearInterpolator() {
}
public LinearInterpolator(Context context, AttributeSet attrs) {
}
public float getInterpolation(float input) {
return input;
}
/** @hide */
@Override
public long createNativeInterpolator() {
return NativeInterpolatorFactoryHelper.createLinearInterpolator();
}
}
顯然我們看到他是輸入什麼輸出什麼,方法getInterpolation(float input)的參數取值在[0,1]上。
AccelerateDecelerateInterpolator
public class AccelerateDecelerateInterpolator extends BaseInterpolator
implements NativeInterpolatorFactory {
public AccelerateDecelerateInterpolator() {
}
@SuppressWarnings({"UnusedDeclaration"})
public AccelerateDecelerateInterpolator(Context context, AttributeSet attrs) {
}
public float getInterpolation(float input) {
return (float)(Math.cos((input + ) * Math.PI) / f) + f;
}
/** @hide */
@Override
public long createNativeInterpolator() {
return NativeInterpolatorFactoryHelper.createAccelerateDecelerateInterpolator();
}
}
從(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f這個我們發現,這是一個餘弦函數y=cos(π+xπ)/2+0.5,x在[0,1]
。不難發現,這個函數在x=[0,1]上y=[0,1],這時y呈遞增趨勢,且增長速率先慢再快再變慢。
BounceInterpolator
在看一下這個類的源碼
public class BounceInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {
public BounceInterpolator() {
}
@SuppressWarnings({"UnusedDeclaration"})
public BounceInterpolator(Context context, AttributeSet attrs) {
}
private static float bounce(float t) {
return t * t * f;
}
public float getInterpolation(float t) {
// _b(t) = t * t * 8
// bs(t) = _b(t) for t < 0.3535
// bs(t) = _b(t - 0.54719) + 0.7 for t < 0.7408
// bs(t) = _b(t - 0.8526) + 0.9 for t < 0.9644
// bs(t) = _b(t - 1.0435) + 0.95 for t <= 1.0
// b(t) = bs(t * 1.1226)
t *= f;
if (t < f) return bounce(t);
else if (t < f) return bounce(t - f) + f;
else if (t < f) return bounce(t - f) + f;
else return bounce(t - f) + f;
}
/** @hide */
@Override
public long createNativeInterpolator() {
return NativeInterpolatorFactoryHelper.createBounceInterpolator();
}
}
再來看一下最核心的部分
t *= ;
if (t < ) return bounce(t);
else if (t < ) return bounce(t - ) + ;
else if (t < ) return bounce(t - ) + ;
else return bounce(t - ) + ;
private static float bounce(float t) {
return t * t * f;
}
從上面的方法中可以發現,函數一開始進行了一次一進制一次函數,将輸入值擴大1.1226倍,函數的取值範圍從[0,1]變成[0,1.1226]
。再看一下下面執行的四段函數。
[0,0.3535]執行一個變換愈來愈快的遞增函數,值範圍是[0,0.999698]
[0.3535,0.7408]執行一個抛物線函數,先遞減在遞增,值範圍是[0.7,1.0001265288]
接下來兩段和第二段執行的類似,隻不過值更大。這個連續起來正好是四次落地的過程
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNvwVZ2x2bzNXak9CX90TQNNkRrFlQKBTSvwFbslmZvwFMwQzLcVmepNHdu9mZvwFVywUNMZTY18CX052bm9CXvJ1RhZmUXFmdKhkW1ZkMMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2LcRHelR3LcJzLctmch1mclRXY39jM1YDNxAzMzEDMxgDM4EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
下面來模仿一下系統提供的小球彈起動畫
首先來看一下給小球設計的運動函數圖
小球總共彈起5次,5次函數分别如下
override fun getInterpolation(t: Float): Float {
if(t<) return bounce(t*)*
else if(t<) return bounce(t*-)*+
else if(t<) return bounce(t*-)*+
else if(t<) return bounce(t*-)*+
else if(t<) return bounce(t*-)*+
else return bounce(t*-)*+
}
看一下效果圖
有沒有發現這個彈的更自然,如果想要彈的更自然的話,可以添加更多的時間段,将運動過程劃分成更多小的過程。
下一篇寫估值器TypeEvaluator