一、安卓动画
动画都是由于人眼观看的延迟,通过一帧一帧绘制连续的图像然后通过GPU显示到屏幕上的,所以无论哪种动画(平移动画、旋转等),图像都是随着时间往后推移而不断变换的。
安卓的动画有很多种供我们使用,比如最简单的Tween Animation(补间动画),帧动画,属性动画,甚至矢量动画。
下面是一个非常简单的平移动画
图像中
- 第一个小球做的是自由下落然后反弹的动画
- 第二个是小球在做上下浮动的动画
- 第三个动画小球先缓慢下降,之后迅速上升的动画
三个小球都不是做的单纯的单向平移。
那怎么才能将一个很简单的平移动画变成这种非单向的稍微复杂的动画呢?可能有人想到了多个动画放一起,简单的情景不排除这种方法,但是这里讲到的是动画的另外一个非常重要的工具——插值器Interpolator。
在安卓anim文件目录下编写一个动画xml文件,例如
这是一个Y轴位移动画,从0到500的位置,用时2秒。
代码中执行:
运行结果:
其实可以看出来,小球并不是匀速运动的,而是开始逐渐加速最后又逐渐减速的动画过程,直到到达end。
为什么呢?
这是因为插值器(Interpolator)的存在,但是我们在代码中并没有使用到它,很简单的动画代码,为什么会有加速减速的过程呢?
其实,我们看看Animation的源码可以发现一段代码
其中的mInterpolator就是当前动画的插值器,如果动画没有被设置指定插值器,那会默认使用AccelerateDecelerateInterpolator,这个插值器就是导致小球先加速后减速的原因。
二、插值器(Interpolator)
讲了那么多插值器,还没有真正的介绍插值器。插值器的用处,用简单的来说,是处理动画执行变化率的。
用白话的方式去解释(用平移动画来解释,其他的旋转动画、透明动画、缩放动画都一样的):
补间动画都是我们设置了“起始值start”、“末尾值end”和“时长s秒”这三个重要的属性,它的意思就是,在s秒内,控件从start的位置运动到end位置。大致就是这样,但是到底是怎么从start位置运动到end位置的,是加速呢,减速呢,还是先减速后加速还是更加复杂的,这个就是动画执行的过程控制。
插值器我们可以用坐标去分析一下动画运动过程:
横坐标代表的是时间流逝,横坐标那个刻度1表示的是总体时间的1,而不是1秒,数学知识学过的总体1
纵坐标代表的是位移进度,同样的1也表示的总体1,比如上面说的控件按照Y轴从0运动到500,那这里的500就表示的总体1
简单点说就是坐标原点表示起始,1表示末尾。
图中的一条直线在数学上就是一条正比例函数,即:s=t,物理上路程s与时间t的这种关系可以叫做匀速运动,斜率不变即匀速,也即是说随着时间匀速变化,该平移运动也是在匀速运动的。
这种解释对照到我们平移运动就是,控件从开始到最后,都是以匀速变化运动到末尾位置的。再来看一个图
这个我们对其运动分析:
控件开始匀速运动,在中间的某个时刻运动到了末尾end位置,然后接着它会匀速的运动到开始start位置
这就是Interpolator的原理
随着时间的流逝,控件到底怎么从起始位置运动到末尾位置的。
我们看Interpolator的源码,它是一个接口,并且继承的一个接口TimeInterpolator
里面没有任何方法。
接着看TimeInterpolator源码:
其中只有一个方法,getInterpolation,它有一个float参数input,和一个float返回值
input参数就是0-1的“时间进度”,float类型的返回值就是0-1的“过程进度”
上面那种最简单的平移动画是用的AccelerateDecelerateInterpolator插值器
AccelerateDecelerateInterpolator源码
它自己实现了getInterpolation的方法,它的运动进程与时间的变化关系式为:
y=cos((t+1)π )/2 + 0.5
用图像表示:
高中物理知识,曲线的切线,就表示速度,斜率(切线倾斜度)越大表示速度越大
该AccelerateDecelerateInterpolator图像表明:
很明显,它的切线斜率是不断变化的,从一开始到中间的一段时间,曲线斜率(即速度)越来越大,但是最后它的速度就会越来越小。
这就是为什么上面的那个简单的平移动画是先加速,然后减速直到到达末尾位置的原因了。
三、几种安卓提供的Interpolator
其实安卓本身有几种供开发者调用的Interpolator,可以在anim文件目录的动画xml文件中设置
也可以代码中设置:
除了默认的AccelerateDecelerateInterpolator以外,
AccelerateInterpolator速度随着时间流逝越来越大(加速运动)
AnticipateInterpolator开始时缓慢向前,后向后越来越快(类似弹射)
BounceInterpolator小球下落弹跳
以及CycleInterpolator、LinearInterpolator等等,可以网上去搜搜各种安卓提供的Interpolator。
三、使用自己的Interpolator,想让过程怎么样就怎么样
只要实现安卓提供的Interpolator接口,重写getInterpolation方法就可以去自己制定动画的过程
1. 先编写一个先慢慢加速运动到结束位置,然后很快的运动到起始位置的动画
先在坐标系中画出运动过程:
根据图像可以知道是两个一次函数:
所以Interpolator可以这么写:
设置自己的插值器:
运行结果:
2. 我们模拟一个小球落下的动画
定义起始位置为高空start,地面为末尾位置end
小球先应该加速下降(也就是从start到end是加速的),然后减速弹起(不过不会弹起到起始位置)
然后又是加速下降,减速弹起
这样几次来回就是一个小球的落地动画了。
那这个动画的Interpolator应该怎么写呢?(这里需要一定的高中物理基础和高中数学基础)
首先需要根据运动过程大致的去画一个曲线(根据斜率越来越大表示加速,斜率越来越小表示减速)
可以简单点去使用抛物线的曲线。
代码中使用:
就可以了