引言
上一篇文章讲到了关于动画的三种不同实现方式,其中讲到了属性动画插值器的使用,这一节,我们就来讲一讲关于属性动画插值器(Interpolator)和估值器(Evaluator)的使用。
知识前瞻
插值器(Interpolator)和估值器(Evaluator)对于实现666的非匀速动画是非常重要的。属性动画提供setInterpolator(TimeInterpolator interpolator)和setEvaluator(TypeEvaluator evaluator)两个方法来设置相关的参数。TimeInterpolator是时间插值器,它的作用是根据时间的流逝比例来计算当前属性值改变的比例,系统提供的有LinearInterpolator(线性插值器)、AccelerateDecelerateInterpretor(加速减速插值器)、DecelerateInterpretor(减速插值器)、AccelerateInterpretor(加速插值器)、CycleInterpolator(循环插值器)等等。下面附上一张插值器的继承实现关系图。
TypeEvaluator是类型估值算法,它的作用是根据当前属性值改变的比例来计算改变后的属性值,系统提供的有IntEvaluator(整型估值器)、FloatEvaluator(浮点型估值器)、ArgbEvaluator(针对Color的属性的估值器)等等。下面附上一张估值器的继承实现关系图。
除了系统提供的这些插值器和估值器,大家也可以根据自己的需要和脑洞来设计一些自己的插值器和估值器,从而实现自己非常酷炫的动画了。
插值器
现在我们看看系统提供的线性插值器,它里面实现的逻辑如下:
/**
* An interpolator where the rate of change is constant
*/
@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();
}
}
从实现方法我们看到线性插值器的输入和输出是一样,也就是说时间改变的比例和属性值改变的比例是一样的,至于改变的属性值变为啥值,我们就需要根据估值器来计算。 那如果我们没有设置估值器,不要着急,系统为我们默认设置了一个整型或者浮点型估值器,看setEvaluator(TypeEvaluator value)的注释就明白了;
/**
* The type evaluator to be used when calculating the animated values of this animation.
* The system will automatically assign a float or int evaluator based on the type
* of <code>startValue</code> and <code>endValue</code> in the constructor. But if these values
* are not one of these primitive types, or if different evaluation is desired (such as is
* necessary with int values that represent colors), a custom evaluator needs to be assigned.
* For example, when running an animation on color values, the {@link ArgbEvaluator}
* should be used to get correct RGB color interpolation.
*
* <p>If this ValueAnimator has only one set of values being animated between, this evaluator
* will be used for that set. If there are several sets of values being animated, which is
* the case if PropertyValuesHolder objects were set on the ValueAnimator, then the evaluator
* is assigned just to the first PropertyValuesHolder object.</p>
*
*/
估值器
既然上面讲到了整型插值器,那我们就接着看整型估值算法;
public class IntEvaluator implements TypeEvaluator<Integer> {
/**
* 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 * (v1 - v0)</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; should be of type <code>int</code> or
* <code>Integer</code>
* @param endValue The end value; should be of type <code>int</code> or <code>Integer</code>
* @return A linear interpolation between the start and end values, given the
* <code>fraction</code> parameter.
*/
public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
int startInt = startValue;
return (int)(startInt + fraction * (endValue - startInt));
}
}
看到这样的实现,小伙伴们都发现估值器和插值器都挺简单的嘛,既然这样的话,那我们就动手实现一个属于我们的插值器和估值器吧。
Demo
下面的例子实现的是二次函数曲线y = x * x的一个动画,mView在X轴是匀速运动,在Y轴是我们自定义的一个一个插值器和估值器。
插值器实现的是当时间流逝的比例和属性值流逝的比例为t*t,这样的话估值器就是一个匀速运动的浮点型估值器了,其实我们也可以反过来,插值器是匀速运动的线性插值器,而估值器是二次函数的一个估值算法,大家有兴趣的可以试一下。
public void startAnim(View view){
AnimatorSet set = new AnimatorSet();
ObjectAnimator translateX = ObjectAnimator.ofFloat(mView, "translationX", 0, 1000);
translateX.setInterpolator(new LinearInterpolator());
ObjectAnimator translateY = ObjectAnimator.ofFloat(mView, "translationY", 0, 1000);
translateY.setInterpolator(new MyInterpolator());
translateY.setEvaluator(new MyTypeEvaluator());
set.setDuration(10000);
set.play(translateX).with(translateY);
set.start();
}
class MyInterpolator implements Interpolator{
@Override
public float getInterpolation(float input) {
return input * input;
}
}
class MyTypeEvaluator implements TypeEvaluator<Float>{
@Override
public Float evaluate(float fraction, Float startValue, Float endValue) {
return startValue + fraction * (endValue - startValue);
}
}
总结
简单的讲解了一下插值器和估值器,可能这样的理解和大家的理解不一样,如有错误,希望大家批评指正,也希望大家给出相关好的建议,谢谢!