当数学遇上动画:讲述 ValueAnimator、TypeEvaluator和TimeInterpolator之间的恩恩怨怨(2)
上一节的结论是,ValueAnimator
就是由TimeInterpolator
和TypeEvaluator
这两个简单函数组合而成的一个复合函数。如下图所示:
上一节我们还将TimeInterpolator
和TypeEvaluator
看作是工厂流水线上的两个小员工,那么ValueAnimator
就是车间主管,TimeInterpolator
这个小员工面对的是产品的半成品,他负责控制半成品输出到下一个生产线的速度,而下一个生产线上的小员工TypeEvaluator
的任务就是打磨半成品得到成品,最后将成品输出。
本小节进一步深究TimeInterpolator
和TypeEvaluator
在动画实现过程中承担的作用以及它们之间的联系与差异。
还是先说结论,借助TimeInterpolator
或者TypeEvaluator
“单独”来控制动画所产生的动画效果殊途同归!
1 两种特殊情况下的ValueAnimator
(1)上一节提到过,假设TimeInterpolator
是LinearInterpolator
(线性插值器,f(t)=t),也就是说时间比率不被“篡改”的话,那么ValueAnimator
对应的函数其实就简化成了TypeEvaluator
函数(F=g(x,a,b)=g(f(t),a,b)=g(t,a,b)),即动画实际上只由TypeEvaluator
来控制。
这里可以理解为,TimeInterpolator
这个员工请假了,但是工厂为了不停止生产安排了一个自动机器人代替他的工作,它只会匀速地将半成品输入到下一个生产线。
(2)同理,我们假设TypeEvaluator
是“LinearTypeEvaluator”
(线性估值器,并没有这个说法,所以加上引号,计算方式就是g(x,a,b)=a+x*(b-a))的话,那么ValueAnimator
对应的函数也可以简化,F=g(x,a,b)=g(f(t),a,b)=a+f(t)*(b-a),即动画实际上只由TimeInterpolator
来控制。
同样的,这里可以理解为,TypeEvaluator
这个员工请假了,默认也有个自动机器人采用默认的操作将半成品加工成最终成品输出。
(3)综上所述,我们来思考上一节留下的问题,即TimeInterpolator
和TypeEvaluator
到底啥关系?
其实TimeInterpolator
是用来控制动画速度的,而TypeEvaluator
是用来控制动画中值的变化曲线的。
虽然它们本质的作用是不同的,但是它们两个既可以联手来控制动画,也可以"单独"
来控制动画(并非真的单独,而是另一方有个默认操作)。
单独控制动画的典型例子就是上一节提到的EaseInterpolator和AnimationEasingFunctions,这两个项目对于制作动画起到殊途同归作用。
为什么说TimeInterpolator
和TypeEvaluator
对于制作动画有着殊途同归的作用呢?
不难想象,在某些定制的情况下,上面两种特殊情况下的构造出来的ValueAnimator
所产生的动画效果是一样的!那如何来验证我们的这个结论呢?我们可以通过构造两个不同的特殊情况下的ValueAnimator
来验证。
下面的代码显示了两个ValueAnimator
,都是在1s中内将float类型的数值从0变化到1。第一个ValueAnimator
使用的是LinearInterpolator
和自定义的TypeEvaluator
,第二个ValueAnimator
使用的是自定义的TimeInterpolator
和"LinearTypeEvaluator"
。打印输出的是两个ValueAnimator
每次值变化的时候的大小。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
ValueAnimator animator1 = new ValueAnimator(); animator1.setFloatValues(0.0f, 1.0f); animator1.setDuration(1000); animator1.setInterpolator(new LinearInterpolator());//传入null也是LinearInterpolator animator1.setEvaluator(new TypeEvaluator() { @Override public Object evaluate(float fraction, Object startValue, Object endValue) { return 100 * fraction; } }); animator1.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { Log.e("demo 1", "" + animation.getAnimatedValue()); } }); ValueAnimator animator2 = new ValueAnimator(); animator2.setFloatValues(0.0f, 1.0f); animator2.setDuration(1000); animator2.setInterpolator(new Interpolator() { @Override public float getInterpolation(float input) { return 100 * input; } }); animator2.setEvaluator(new TypeEvaluator() { @Override public Object evaluate(float fraction, Object startValue, Object endValue) { return fraction; } }); animator2.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { Log.e("demo 2", "" + animation.getAnimatedValue()); } }); animator1.start(); animator2.start(); |
打印输出的结果如下图所示,从图中可以看出,两个ValueAnimator
的在真实时间序列中的输出结果是一样的,也就说明如果将它们作用在同一个View组件的某个属性上的话,那么产生的动画效果是完全一样的。例如,可以将两个ValueAnimator
改成ObjectAnimator
,并将其作用在两个不同的TextView的translationY
属性上,你可以看到一样的动画效果。所以说,在特殊的单独控制动画的情况下,TimeInterpolator
和TypeEvaluator
对于制作动画有着殊途同归的作用。(注意结论的前提,那就是在我们理解了ValueAnimator
内部动画原理之后自己定制的一些特殊情况,它们并非总是能够产生一样的动画效果)
2 简单动画实例分析:弹跳!
经过前面的分析,我们差不多理解了ValueAnimator
是怎么借助TimeInterpolator
和TypeEvaluator
来实现动画的了。在实现动画的时候,为了简便,我们常常可以选择将TimeInterpolator
设置为LinearInterpolator
或者将TypeEvaluator
设置为"LinearTypeEvaluator"
这两种特殊的方式。
举个栗子!假设我们要来实现弹跳的动画效果。首先我们要确定一个弹跳效果的函数曲线,自己想不太好想,我们先来看看项目EaseInterpolator中的EaseBounceOutInterpolator
内部表示的函数曲线的形态。如下图所示,它是一个分段函数,每个段内都是一个简单的二次曲线。如果将这个曲线作用在View组件的translationY
属性上,那么组件将在垂直方向上来回地跳动从而就形成了弹跳的效果。
我们先看下EaseBounceOutInterpolator
的核心方法getInterpolation
的实现,它其实就是刻画了上面的函数曲线。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
//传入的参数input就是动画的时间比率值fraction public float getInterpolation(float input) { if (inputpan class="crayon-t">float input) { if (inputcode>ValueAnimator就是由 TimeInterpolator 和TypeEvaluator 这两个简单函数组合而成的一个复合函数。如下图所示:
上一节我们还将 本小节进一步深究 还是先说结论,借助 1 两种特殊情况下的ValueAnimator(1)上一节提到过,假设 这里可以理解为, (2)同理,我们假设 同样的,这里可以理解为, (3)综上所述,我们来思考上一节留下的问题,即 单独控制动画的典型例子就是上一节提到的EaseInterpolator和AnimationEasingFunctions,这两个项目对于制作动画起到殊途同归作用。 为什么说 不难想象,在某些定制的情况下,上面两种特殊情况下的构造出来的 下面的代码显示了两个
打印输出的结果如下图所示,从图中可以看出,两个 2 简单动画实例分析:弹跳!经过前面的分析,我们差不多理解了 举个栗子!假设我们要来实现弹跳的动画效果。首先我们要确定一个弹跳效果的函数曲线,自己想不太好想,我们先来看看项目EaseInterpolator中的 我们先看下
|