属性动画使用解析(三):理解TimeInterpolator插值器和TypeEvaluator估值器

对于TimeInterpolator插值器和TypeEvaluator估值器主要在理解其作用,因为系统已经内置了多种估值器和插值器,已经能够满足多数的动画需要了。

TimeInterpolator插值器

看下插值器接口源码:

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

说白了float getInterpolation(float input)这个方法的input参数就是代表的当前动画的执行的时间进度,它的取值范围是从0-1.0,代表了动画从开始执行到结束的时间进度,所以这个接口叫做TimeInterpolator意思也非常明白。
这个方法的返回值就非常灵活了,可以小于0,也可以大于1.0,总之在动画的执行时间进度内,可以返回自己需要的值,可以使用input的值作为返回依据,甚至也可以完全不依赖input参数,来为后面的估值器做计算准备。
然后看下Interpolator:

/**
 * An interpolator defines the rate of change of an animation. This allows
 * the basic animation effects (alpha, scale, translate, rotate) to be 
 * accelerated, decelerated, repeated, etc.
 */
public interface Interpolator extends TimeInterpolator {
    // A new interface, TimeInterpolator, was introduced for the new android.animation
    // package. This older Interpolator interface extends TimeInterpolator so that users of
    // the new Animator-based animations can use either the old Interpolator implementations or
    // new classes that implement TimeInterpolator directly.
}

实际上Interpolator接口在API 1的时候就存在了,之所以继承了TimeInterpolator,是因为这样可以使得之前实现Interpolator的插值器可以直接在属性动画中使用,也就是说保证其兼容性。
这里自定义一个简单的插值器,在ValueAnimator中设置运行,并观察其返回值:

        TimeInterpolator timeInterpolator = new TimeInterpolator() {
            @Override
            public float getInterpolation(float input) {
                Log.d("进度", input+"");
                return input;
            }
        };
        ValueAnimator animator = ValueAnimator.ofFloat(100, 400);
        animator.setInterpolator(timeInterpolator);
        animator.setDuration(500);
        animator.start();

打印输出:

08-13 11:06:30.494 24725-24725/com.franky.test D/进度: 0.0
08-13 11:06:30.519 24725-24725/com.franky.test D/进度: 0.0
08-13 11:06:30.662 24725-24725/com.franky.test D/进度: 0.278
08-13 11:06:30.706 24725-24725/com.franky.test D/进度: 0.378
08-13 11:06:30.726 24725-24725/com.franky.test D/进度: 0.424
08-13 11:06:30.744 24725-24725/com.franky.test D/进度: 0.462
08-13 11:06:30.762 24725-24725/com.franky.test D/进度: 0.5
08-13 11:06:30.781 24725-24725/com.franky.test D/进度: 0.54
08-13 11:06:30.801 24725-24725/com.franky.test D/进度: 0.578
08-13 11:06:30.820 24725-24725/com.franky.test D/进度: 0.616
08-13 11:06:30.840 24725-24725/com.franky.test D/进度: 0.654
08-13 11:06:30.860 24725-24725/com.franky.test D/进度: 0.692
08-13 11:06:30.877 24725-24725/com.franky.test D/进度: 0.73
08-13 11:06:30.896 24725-24725/com.franky.test D/进度: 0.768
08-13 11:06:30.916 24725-24725/com.franky.test D/进度: 0.806
08-13 11:06:30.934 24725-24725/com.franky.test D/进度: 0.844
08-13 11:06:30.953 24725-24725/com.franky.test D/进度: 0.882
08-13 11:06:30.972 24725-24725/com.franky.test D/进度: 0.92
08-13 11:06:30.993 24725-24725/com.franky.test D/进度: 0.958
08-13 11:06:31.010 24725-24725/com.franky.test D/进度: 0.996
08-13 11:06:31.029 24725-24725/com.franky.test D/进度: 1.0

验证了前面说的input的取值范围为0-1.0
Interpolator的直接实现类为BaseInterpolator:

abstract public class BaseInterpolator implements Interpolator {
    private @Config int mChangingConfiguration;
    /**
     * @hide
     */
    public @Config int getChangingConfiguration() {
        return mChangingConfiguration;
    }

    /**
     * @hide
     */
    void setChangingConfiguration(@Config int changingConfiguration) {
        mChangingConfiguration = changingConfiguration;
    }
}

该类没有特别说明,方法也不对外公开,猜测为系统内部使用,而该类的子类就是多种插值器的实现了:
内置插值器
其中的LinearInterpolator线性插值器实现:

@HasNativeInterpolator
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()方法直接返回了input参数,和上面的自定义的插值器返回一样,其他具体各类的实现这里不再列出,主要就是根据各种数学公式来进行不同的数值计算,完成不同的实现效果。

TypeEvaluator估值器

首先看看其源码:

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);

}

可以看到TypeEvaluator<T>使用了泛型,因此evaluate()方法的返回值可以为任意类型,方便进行自定义估值器。
evaluate()方法中的各参数意义:

  • fraction参数即为Interpolator插值器中的getInterpolation()方法返回值;
  • startValue为动画执行过程中Values可变参数中各阶段的开始值;
  • endValue为动画执行过程中Values可变参数中各阶段的开始值;

    evaluate()的返回值即利用这三个参数进行相应的计算来返回动画执行阶段所需要的值。
    系统内置的估值器实现:
    内置的估值器
    看下FloatEvaluator中的实现:

public class FloatEvaluator implements TypeEvaluator<Number> {

    public Float evaluate(float fraction, Number startValue, Number endValue) {
        float startFloat = startValue.floatValue();
        return startFloat + fraction * (endValue.floatValue() - startFloat);
    }

返回值的计算方法也很容易理解。
比如使用上面的自定义插值器,然后模拟FloatEvaluator自定义一个TypeEvaluator,在ValueAnimator中设置运行,并观察其返回值:

 TimeInterpolator timeInterpolator = new TimeInterpolator() {
            @Override
            public float getInterpolation(float input) {
                return input;
            }
        };

        TypeEvaluator<Float> typeEvaluator = new TypeEvaluator<Float>() {
            @Override
            public Float evaluate(float fraction, Float startValue, Float endValue) {
                Log.d("进度", fraction + "--"+startValue+"--"+endValue);
                return startValue + (endValue - startValue) * fraction;
            }
        };

        ValueAnimator animator = ValueAnimator.ofFloat(0, 400);
        animator.setInterpolator(timeInterpolator);
        animator.setEvaluator(typeEvaluator);
        animator.setDuration(500);
        animator.start();

返回值:

08-13 11:31:54.291 25739-25739 D/进度: 0.0--0.0--400.0--0.0
08-13 11:31:54.354 25739-25739 D/进度: 0.0--0.0--400.0--0.0
08-13 11:31:54.486 25739-25739 D/进度: 0.272--0.0--400.0--108.8
08-13 11:31:54.524 25739-25739 D/进度: 0.35--0.0--400.0--140.0
08-13 11:31:54.538 25739-25739 D/进度: 0.388--0.0--400.0--155.20001
08-13 11:31:54.556 25739-25739 D/进度: 0.422--0.0--400.0--168.8
08-13 11:31:54.572 25739-25739 D/进度: 0.458--0.0--400.0--183.2
08-13 11:31:54.589 25739-25739 D/进度: 0.492--0.0--400.0--196.8
08-13 11:31:54.607 25739-25739 D/进度: 0.526--0.0--400.0--210.40001
08-13 11:31:54.625 25739-25739 D/进度: 0.562--0.0--400.0--224.79999
08-13 11:31:54.641 25739-25739 D/进度: 0.596--0.0--400.0--238.40001
08-13 11:31:54.659 25739-25739 D/进度: 0.632--0.0--400.0--252.80002
08-13 11:31:54.676 25739-25739 D/进度: 0.666--0.0--400.0--266.4
08-13 11:31:54.694 25739-25739 D/进度: 0.7--0.0--400.0--280.0
08-13 11:31:54.712 25739-25739 D/进度: 0.736--0.0--400.0--294.4
08-13 11:31:54.730 25739-25739 D/进度: 0.77--0.0--400.0--308.0
08-13 11:31:54.746 25739-25739 D/进度: 0.806--0.0--400.0--322.4
08-13 11:31:54.763 25739-25739 D/进度: 0.84--0.0--400.0--336.0
08-13 11:31:54.780 25739-25739 D/进度: 0.876--0.0--400.0--350.4
08-13 11:31:54.799 25739-25739 D/进度: 0.91--0.0--400.0--364.0
08-13 11:31:54.816 25739-25739 D/进度: 0.944--0.0--400.0--377.6
08-13 11:31:54.834 25739-25739 D/进度: 0.98--0.0--400.0--392.0
08-13 11:31:54.851 25739-25739 D/进度: 1.0--0.0--400.0--400.0

可以观察到随着进度fraction的增加,返回值在不断变化。
这里如果设置两个以上的Values打印会发生变化:

TimeInterpolator timeInterpolator = new TimeInterpolator() {
            @Override
            public float getInterpolation(float input) {
                return input;
            }
        };

        TypeEvaluator<Float> typeEvaluator = new TypeEvaluator<Float>() {
            @Override
            public Float evaluate(float fraction, Float startValue, Float endValue) {
                float currentValue = startValue + (endValue - startValue) * fraction;
                Log.d("进度", fraction + "--"+startValue+"--"+endValue+"--"+currentValue);
                return currentValue;
            }
        };
        //增加ofFloat参数个数 
        ValueAnimator animator = ValueAnimator.ofFloat(0,100,200,300,400);
        animator.setInterpolator(timeInterpolator);
        animator.setEvaluator(typeEvaluator);
        animator.setDuration(500);
        animator.start();

打印结果:

08-13 11:35:40.714 25977-25977 D/进度: 0.0--0.0--100.0--0.0
08-13 11:35:40.750 25977-25977 D/进度: 0.0--0.0--100.0--0.0
08-13 11:35:40.873 25977-25977 D/进度: 0.944--0.0--100.0--94.4
08-13 11:35:40.917 25977-25977 D/进度: 0.24800003--100.0--200.0--124.8
08-13 11:35:40.927 25977-25977 D/进度: 0.39199996--100.0--200.0--139.2
08-13 11:35:40.943 25977-25977 D/进度: 0.536--100.0--200.0--153.6
08-13 11:35:40.959 25977-25977 D/进度: 0.67200005--100.0--200.0--167.20001
08-13 11:35:40.975 25977-25977 D/进度: 0.80799997--100.0--200.0--180.79999
08-13 11:35:40.993 25977-25977 D/进度: 0.952--100.0--200.0--195.20001
08-13 11:35:41.012 25977-25977 D/进度: 0.08800006--200.0--300.0--208.8
08-13 11:35:41.029 25977-25977 D/进度: 0.22399998--200.0--300.0--222.4
08-13 11:35:41.047 25977-25977 D/进度: 0.36800003--200.0--300.0--236.8
08-13 11:35:41.065 25977-25977 D/进度: 0.50399995--200.0--300.0--250.4
08-13 11:35:41.081 25977-25977 D/进度: 0.6400001--200.0--300.0--264.0
08-13 11:35:41.098 25977-25977 D/进度: 0.7839999--200.0--300.0--278.4
08-13 11:35:41.117 25977-25977 D/进度: 0.9200001--200.0--300.0--292.0
08-13 11:35:41.132 25977-25977 D/进度: 0.055999994--300.0--400.0--305.6
08-13 11:35:41.150 25977-25977 D/进度: 0.20000005--300.0--400.0--320.0
08-13 11:35:41.168 25977-25977 D/进度: 0.33599997--300.0--400.0--333.6
08-13 11:35:41.183 25977-25977 D/进度: 0.47199988--300.0--400.0--347.19998
08-13 11:35:41.202 25977-25977 D/进度: 0.61599994--300.0--400.0--361.6
08-13 11:35:41.219 25977-25977 D/进度: 0.7520001--300.0--400.0--375.2
08-13 11:35:41.237 25977-25977 D/进度: 0.888--300.0--400.0--388.8
08-13 11:35:41.254 25977-25977 D/进度: 1.0--300.0--400.0--400.0

可以看到startValueendValue会根据设置的values参数个数进行区间的划分,保证在动画的执行阶段能够根据values的参数变化来计算不同的返回值。

总结

  • 插值器提供动画执行的变化因子;
  • 估值器提供动画执行的具体值;

    明白了插值器和估值器的用途,在自定义的时候就能够比较清晰地进行使用了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值