天天看点

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