属性动画中Interpolator原理

来源:互联网 发布:电脑文件数据恢复 编辑:程序博客网 时间:2024/06/05 08:43

属性动画中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

原创粉丝点击