天天看點

Android動畫中的插值器Interpolator使用

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]

接下來兩段和第二段執行的類似,隻不過值更大。這個連續起來正好是四次落地的過程

Android動畫中的插值器Interpolator使用
下面來模仿一下系統提供的小球彈起動畫

首先來看一下給小球設計的運動函數圖

Android動畫中的插值器Interpolator使用

小球總共彈起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