原文章地址在此
概述
属性动画系统是一个强大的动画框架系统,几乎可以利用它来使任何对象动起来。你可以定义一个动画在一段时间内来指定任何对象的属性变化,无论该对象是否在当前屏幕中出现。你可以指定某个对象的某个属性在一段时间内发生变化。为了使其动起来,比如改变对象在屏幕上的位置,那么就需要指定指定这次动画的持续时间以及具体的改变距离。
属性动画系统可让您定义一个动画过程中的以下几点
- 持续时间:你可以指定动画的持续时间。默认长度为300毫秒。
- 时间插值:您可以指定该属性的值来修改动画的时间轨迹(此处翻译的不甚理想,原文为Time interpolation: You can specify how the values for the property are calculated as a function of the animation’s current elapsed time.)
- 重复次数和行为:你可以为一个动画指定是否重复执行,以及重复执行的次数。您还可以指定是否动画反向执行。也可设置循环执行动画(即正向-反向-正向的顺序),直至到达重复次数。
- 动画集:您可以将动画成一起执行或按照指定的延迟有序执行
- 帧刷新延迟:您可以指定多久刷新动画的帧。默认设置刷新每10毫秒,但在你的应用程序可以刷新帧最终取决于系统的繁忙程度和手机性能。
属性动画的工作原理
首先,让我们看看一个简单的属性动画原理示例。如下图,其一个假设对象X属性,它表示在画面上的水平位置。动画的持续时间被设定为40毫秒,行进的距离是40个像素。每隔10毫秒(这是默认的帧刷新速率),这个对象水平方向移动10个像素。在40毫秒结束时,动画停止,并且对象位于水平位置40像素处,这是一个线性时间插值动画的例子,这意味着是一个恒定速度的物体在运动。
还可以指定个具有非线性内插的动画。下图指定了一个开始时加速,在结束时减速的动画对象。仍然是在40毫秒内移动了40个像素,但非匀速度。在开始的时候,这个动画加速到中间点,然后减速,直到动画结束。行进的距离在开始和结束小于在中间时间的距离。
让我们来仔细看一下属性动画是如何计算如上所示的那些动画。下图表示出了主要的类与其内部类是如何工作的。
ValueAnimator类同动画的时间相关联,如动画已经运行多长时间,以及它的动画属性的当前值。
ValueAnimator类封装了TimeInterpolator类(用来定义时间插值)和TypeEvaluator类(该类定义了如何计算已经开始执行的动画的值)。例如,在图2中,TimeInterpolator类使用了 AccelerateDecelerateInterpolator(非线性时间插值)、而TypeEvaluator的类型为IntEvaluator。
要创建一个属性动画,需要创建一个ValueAnimator类,并指定它的初值和终值,以及动画的时间属性。当你调用start()方法时动画开始。在整个动画过程中,ValueAnimator类会基于该动画的持续时间和还有多少时间结束计算出一个0-1之间的值(暂时称之为已完成分数)。该值表示动画已完成的百分比,0为0%、1为100%。例如,在图1中,在t=10毫秒时,该值将是0.25,因为总的持续时间为t = 40毫秒,且图1为线性时间插值。
当ValueAnimator类完成计算已完成分数时,它调用预先指定的TimeInterpolator对象来计算一个内插的分数。用来同预设的时间插值相对应。例如,在图2中,在t = 10毫秒处,因为动画缓慢加速时,内插的分数,约为0.15,小于已完成分数0.25。而在图1中,内插的分数总是同已完成分数相等。
当内插的分数的计算完成,是由ValueAnimator类调用指定TypeEvaluator基于整体位置和内插的分数来计算已执行动画的属性的值。例如,在图2中,在t = 10毫秒处内插的分数为0.15,所以当时该属性的值为0.15×(40 - 0),即6。
更多示例请参考com.example.android.apis.animation包中的API演示示例项目。
属性动画和视图动画的区别
视图动画只支持View对象来使用,所以如果你想使非View对象动起来,你必须自己通过代码来实现该功能。视图动画系统也受限于只支持少量的View动画特性。比如你可以如对一个View进行的缩放和旋转,但无法改变其背景颜色。
视图动画系统的另一个缺点是,它仅修改其View绘制,而不是实际的View本身的属性。举例来说,如果你使一个按钮在屏幕上移动,按钮的绘制是正确的,但在此时按钮的可点击实际位置不会改变,以至于开发者要实现自己通过代码来处理这个问题。
但是在属性动画系统中,这些问题已经完全不复存在,可以对任何对象(View对象和非View对象)的任何属性来执行(并且这些属性会真的被改变)。属性动画系统执行的动画的方式也更加健壮。在更高的层次上,分配给animators 要执行动画的属性,如颜色,位置或大小,也可以定义动画的方方面面,如插值和多个动画同步。
但是视图动画系统,将会花费较少的时间和代码量。如果已有的代码已经达到你预期的效果,就没有必要使用属性动画系统来替换。可以尝试在不同的情况下使用不同的动画系统来解决问题。
API概述
大部分的属性动画系统的API都位于android.animation下。因为视图动画系统已经定义了许多插值android.view.animation,属性动画系统也可以使用。下表描述的属性动画系统的主要组成部分
Animators
该动画类提供的基本结构,用于创建动画。通常不建议直接使用这个类,因为使用它需要你实现大量的方法。下面的是子类扩展动画:
- ValueAnimator 计算属性动画在运动时的主要时序引擎。它的所有核心功能包括了,计算动画值和包含每个动画的时间细节,一个动画是否重复的信息,接收动画更新事件的监听器,并能够设置自定义类型评估。有两部分动画属性:计算动画的相关数值以及把计算后的数值设定在正在动画对象的相关属性上。ValueAnimator无法重复得到,所以你必须通过监听由ValueAnimator计算值更新和修改的对象的事件,来实现你自己的逻辑
- ObjectAnimator ValueAnimator的子类,可以为其指定一个动画对象以及该对象的动画属性,该对象会随着动画的执行来改变动画对象的对应属性,由于使用该类指定一个动画的过程更加简单,所以通常情况下你会使用这个类来完成一个属性动画。但是由于ObjectAnimator的一些限制,有时还是会直接ValueAnimator类,比如需要一个特定的acessor方法的动画对象时
- AnimatorSet 提供了一种机制,让单个的动画有了组的概念。可以设置动画同时执行,按照顺序执行,或在指定的延迟后执行
Evaluators
Evaluators 告诉属性动画系统如何计算一个给定的属性值。基于Animator类提供的时序数据、动画的开始和结束值,来计算动画属性值。属性动画系统提供以下Evaluators 类:
- IntEvaluator 为int类型属性准备的默认Evaluators类
- FloatEvaluator 为float类型属性准备的默认Evaluators类
- ArgbEvaluator 为颜色属性(十六进制值)类型属性准备的默认Evaluators类
- TypeEvaluator 一个允许你创建你自己的Evaluators类的接口。如果你希望对一个不是前三种属性来执行的动画,你就必须实现TypeEvaluator接口来指定如何计算对象属性值的动画。当你希望同默认的实现有所不同时,你也可以对前三种属性来指定一个TypeEvaluator对象
Interpolators
Interpolators定义了一个同时间关联的计算函数,通过该函数,可以得到指定时间点上对应的属性值。例如,可以指定在整个动画过程中线性发生动画,即动画在整个时间内均匀地移动,或者你可以指定要使用的非线性时,比如图2那种运动方式的动画。下面的类描述了在android.view.animation中包含的Interpolators类。如果没有适合您的需要的Interpolators实现,自行实现TimeInterpolator接口即可。
- AccelerateDecelerateInterpolator 开始和结束缓慢但加速通过中间
- AccelerateInterpolator 慢慢加速,从慢到快
- AnticipateInterpolator 先退后一些,然后向前
- AnticipateOvershootInterpolator 先退后一些,然后向前 ,超过指定数值后再回退
- BounceInterpolator 达到指定数值后反弹
- CycleInterpolator 按照指定次数循环
- DecelerateInterpolator 慢慢减速,从快到慢
- LinearInterpolator 线性,变化恒定
- OvershootInterpolator 超过指定数值后再回退
- TimeInterpolator 自定义Interpolators需要实现的接口