当数学遇上动画(1)

609 查看

当数学遇上动画:讲述 ValueAnimator、TypeEvaluator和TimeInterpolator之间的恩恩怨怨(1)

其实关于 ValueAnimator 的内部工作原理大家也都清楚,本文只是选择从数学函数的角度来解析这个原理,方便理解。看完了本节之后我们就更加清楚如何借助 TypeEvaluator 和 TimeInterpolator 来帮助我们实现动画等知识。

本系列文章共有三篇,第一篇通过源码解析ValueAnimator类,第二篇通过实例解析TimeInterpolatorTypeEvaluator,第三篇分析常见动画背后的缓动函数,最后引出一个新的Android动画开发的辅助库Yava

1 Android动画基础知识

(1)狭义而言,动画一般就是指某个View组件的某个或者某些属性值在一段时间内不断变化的过程,这个变化过程往往有个起始值、结束值和一系列的中间值,ValueAnimator就是用来反映这个属性值变化过程的重要类,所以本文的介绍主要是以分析ValueAnimator为主。 (2)如果将属性值的变化过程看做一个数学函数的话,从动画效果上来看它是连续的,但实际上它还是离散的,因为它实际上也就是通过插入中间值(简称插值)从而”一帧一帧”完成动画的,那每一帧在哪里取,取多少呢?这也就是ValueAnimator类主要完成的作用。

那到底ValueAnimator是怎么控制属性值的变化过程的呢?答案是借助TimeInterpolatorTypeEvaluator来帮忙!TimeInterpolator用来控制在哪里取,而TypeEvaluator用来控制取多少。(注:取多少个点进行插值是不确定的,例如动画持续时间1s,可能取60,也可能取54、57或者58个中间点进行插值)

先说本小节结论,每一个ValueAnimator其实就是一个的TimeInterpolator和一个TypeEvaluator的结合体。从数学的角度来看,ValueAnimator就是由TimeInterpolatorTypeEvaluator这两个简单函数组合而成的一个复合函数。用图来表述如下:

img

你也可以将TimeInterpolatorTypeEvaluator看作是工厂流水线上的两个小员工,那么ValueAnimator就是车间主管啦。TimeInterpolator这个小员工面对的是产品的半成品,他负责控制半成品输出到下一个生产线的速度。而下一个生产线上的小员工TypeEvaluator的任务就是打磨半成品得到成品,最后将成品输出。

2 结合源码解释函数形式

(1)假设TimeInterpolator是函数x=f(t),t表示动画已经完成的时间比率(例如动画的总时长是10s,已经过了4s了,那么t=0.4),所以t的取值范围是[0,1],0表示动画开始,1表示动画结束。该函数的返回值指的是动画实际插值的时间点,一般是0到1之间,但是也可以小于0(”下冲”)或者大于1(”上冲”)。 该函数的作用是把当前时间进度映射成另一个值,这样动画参照的时间由此被”篡改”,动画的速度由此被改变。 (后面还有详细介绍)

参考接口TimeInterpolator的定义:

(2)假设TypeEvaluator是函数y=g(x,a,b),x就是前面函数f(t)篡改之后的插值的时间点,a、b分别表示属性动画的起始值和结束值。 该函数的作用是通过起始值、结束值以及插值时间点来计算在该时间点的属性值应该是多少。

参考接口TypeEvaluator的定义:

(3)假设TimeInterpolatorTypeEvaluator是上面两个简单函数,那么ValueAnimator也是一个函数,它其实就是表示TimeInterpolator的函数x=f(t)和表示TypeEvaluator的函数y=g(x,a,b)结合而成的复合函数F=g(f(t),a,b)

参考ValueAnimatoranimateValue方法的定义:

3 通俗解析各个击破

3.1 关于ValueAnimator

(0)ValueAnimator就是一个的TypeEvaluator和一个TimeInterpolator的结合体,所以该类有两个方法分别用来设置动画的TypeEvaluatorTimeInterpolator。 (1)setInterpolator方法可以不调用,默认是加速减速插值器AccelerateDecelerateInterpolator,但是如果调用且传入的参数为null的话,那么就会被设置成线性插值器LinearInterpolator (暂时不清楚为什么要这样做)。 (2)setEvaluator方法也可以不调用,默认会根据属性值的类型设置一个IntEvaluator或者FloatEvaluator。后面会讲到这类TypeEvaluator可以看作是线性估值器"LinearTypeEvaluator"并没有这个说法,因故加上引号)。

参考ValueAnimator的部分源码: