属性动画中Interpolator原理

属性动画中Interpolator的使用

Android中可以通过setInterpolator()给一个属性动画设置一个补间器,定义一个动画改变的速率,可以让一个动画做非线性的动作,比如加速或者减速,Android提供了很多功能不同的Interpolator共开发者使用,它们都是继承自TimeInterpolator,如图:

image

如下代码让progressBar的进度从0变化到100,并且是先加速后减速。

       valueAnimator = ValueAnimator.ofInt(0,100);
        valueAnimator.setDuration(2000);
        valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                int p = (int) animation.getAnimatedValue();
                progressBar.setProgress(p);
            }
        });
        valueAnimator.start();

Interpolator的内部实现

先看看TimeInterpolator的源码,内部只有一个getInterpolation()方法,方法接收一个input参数,这个参数是从0到1变化的,0代表是动画开始,1代表的是变化结束,中间的值随着动画运行在0到1之间变化,实现具体的interpolator只要实现getInterpolation()方法,根据需要自己通过input参数去计算出interpolator就可以了。算出了这个值是怎么使用的呢,就得引出另外一个概念TypeEvaluator

/**
 * 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);
}

TypeEvaluator介绍

TypeEvaluator用来计算动画如何从初始值过渡到结束值,代码很简单,只有一个计算方法,这个方法接收三个参数,fraction,从动画开始到结束的分数,另外两个是动画开始的值和结束的值,使用这三个参数可以计算出某个时刻动画当前的值

public interface TypeEvaluator<T> {

    /**
     * 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 * (x1 - x0)</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.
     * @param endValue   The end value.
     * @return A linear interpolation between the start and end values, given the
     *         <code>fraction</code> parameter.
     */
    public T evaluate(float fraction, T startValue, T endValue);

}

系统的ofIntofFloat动画变化对应TypeEvaluator的实现类IntEvaluatorFloatEvaluator看看IntEvaluator的实现,动画结束值减去开始值算出差值,再乘以当前的动画执行分数fraction,再加上开始值就得到了当前的动画的值,我们可以通过实现TypeEvaluator去定制自己的Evaluator,然后就可以ofObject去使用啦

public class IntEvaluator implements TypeEvaluator<Integer> {

    public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
        int startInt = startValue;
        return (int)(startInt + fraction * (endValue - startInt));
    }
}

Interpolator和TypeEvaluator的关系

TypeEvaluator计算当前动画值所传入的fraction的值就是通过Interpolator的getInterpolator计算出来的,最简单的一种及时线性的变化,比如系统的LinearInterpolator直接将input返回,这样fraction匀速的从0变到1,那么动画的值也就从起始值匀速的变化到结束值。

public class LinearInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {

    public float getInterpolation(float input) {
        return input;
    }

}

再来看看AccelerateDecelerateInterpolator代码

public class AccelerateDecelerateInterpolator implements Interpolator, NativeInterpolatorFactory {  
    public float getInterpolation(float input) {  
        return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;  
    }  

}  

AccelerateDecelerateInterpolator实现动画先加速后减速,可以看到他的算法,input从0到1,(input + 1) * Math.PI)从π到2π,cos(π~2π)变化根据三角函数是从-1 ~ 1,再除以2加上0.5刚好是0-1区间内变化,不同的是中间的变化是先加速在减速,这样就实现了动画先加速再减速的变化啦

image

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值