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 + 1) * Math.PI) / 2.0f) + 0.5f;
    }

    /** @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 * 8.0f;
    }

    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 *= 1.1226f;
        if (t < 0.3535f) return bounce(t);
        else if (t < 0.7408f) return bounce(t - 0.54719f) + 0.7f;
        else if (t < 0.9644f) return bounce(t - 0.8526f) + 0.9f;
        else return bounce(t - 1.0435f) + 0.95f;
    }

    /** @hide */
    @Override
    public long createNativeInterpolator() {
        return NativeInterpolatorFactoryHelper.createBounceInterpolator();
    }
}

再来看一下最核心的部分

t *= 1.1226f;
if (t < 0.3535f) return bounce(t);
else if (t < 0.7408f) return bounce(t - 0.54719f) + 0.7f;
else if (t < 0.9644f) return bounce(t - 0.8526f) + 0.9f;
else return bounce(t - 1.0435f) + 0.95f;
private static float bounce(float t) {
    return t * t * 8.0f;
}

从上面的方法中可以发现,函数一开始进行了一次一元一次函数,将输入值扩大1.1226倍,函数的取值范围从[0,1]变成[0,1.1226]
。再看一下下面执行的四段函数。
[0,0.3535]执行一个变换愈来愈快的递增函数,值范围是[0,0.999698]
[0.3535,0.7408]执行一个抛物线函数,先递减在递增,值范围是[0.7,1.0001265288]
接下来两段和第二段执行的类似,只不过值更大。这个连续起来正好是四次落地的过程
函数图像

下面来模仿一下系统提供的小球弹起动画

首先来看一下给小球设计的运动函数图
这里写图片描述
小球总共弹起5次,5次函数分别如下

override fun getInterpolation(t: Float): Float {
            if(t<0.1746) return bounce(t*1.1226f)*26
            else if(t<0.447) return bounce(t*1.1226f-0.35f)*26+0.4f
            else if(t<0.6716) return bounce(t*1.1226f-0.63f)*26+0.6f
            else if(t<0.8205) return bounce(t*1.1226f-0.8435f)*26+0.8f
            else if(t<0.9424) return bounce(t*1.1226f-0.9935f)*36+0.85f
            else return bounce(t*1.1226f-1.0935f)*48+0.94f
        }

看一下效果图

有没有发现这个弹的更自然,如果想要弹的更自然的话,可以添加更多的时间段,将运动过程划分成更多小的过程。
下一篇写估值器TypeEvaluator

猜你喜欢

转载自blog.csdn.net/android_hdh/article/details/81561794