属性动画简介
属性动画系统是一个强大的框架,可以让任何对象加上动画效果。随着时间的推移,您可以定义一个动画来改变任何对象属性,无论它是否显示在屏幕上。在指定的时间长度,属性动画改变属性值(对象的字段)。通过指定对象属性来创造动画效果,比如View在屏幕上的位置,动画的时长,以及动画值的改变。
属性动画系统可以让您定义一个动画的以下特征:
- 持续时间(Duration):你可以指定一个动画的持续时间。默认长度为300毫秒。
- 时间插值器(Time interpolation):您可以指定属性的值如何计算作为动画当前所用时间的函数。
- 重复和行为(Repeat count and behavior):你可以指定是否有一个动画重复时,达到持续时间的结束,有多少次重复动画。您还可以指定是否希望动画反向播放。设置它反向播放动画,然后反复重复,直到达到重复的数量。
- 动画设置(AnimatorSets):你可以动画成逻辑组,同时或顺序或在指定的延迟。
- 帧刷新延迟(FrameRefreshDelay):你可以指定如何经常刷新你的动画帧。默认设置为刷新每10毫秒,但您的应用程序可以刷新帧的速度最终取决于系统的整体是如何的,以及该系统可以为底层定时器服务的速度。 一般使用系统默认即可。
属性动画如何工作
首先,让我们用一个简单的例子来说明一个动画。图1描绘了一个假设的对象,它的X属性是动画的,它代表了它在屏幕上的水平位置。动画的持续时间设置为40毫秒,和旅行的距离为40像素。每10毫秒,这是默认的帧刷新率,对象水平移动10个像素。在为结束,动画停止,和物体两端在水平位置40。这是一个用线性插值动画的例子,这意味着对象以一个恒定的速度移动。
你也可以指定动画有一个非线性插值。图2说明了一个假设的对象,在动画开始时加速,然后减速动画结束时。该对象仍然在40毫秒内移动40个像素,但非线性。在开始的时候,这个动画加速到中途点,然后从中途点减速直到动画结束。如图2所示,在动画的开始和结束的距离是小于在中间。
接下来看看属性动画系统的重要组成部分是如何计算像上面所示的动画的动画系统。图3描述了主类是如何相互工作的。
ValueAnimator对象保持跟踪在动画的整个运行时间,如动画已经运行多久,当前动画的值。
ValueAnimator封装Timeinterpolator和TypeEvaluator,它定义了如何计算对象被动画对应的值。例如,在图2中,使用的timeinterpolator对应AccelerateDecelerateInterpolator,TypeEvaluator对应intevaluator。
当开始一个动画,创建一个ValueAnimator并给它动画的开始和结束值的属性,以及动画的持续时间。当你调用start()方法时 动画开始。整个动画中,ValueAnimator计算一个百分比,基于动画的持续时间和经过了多少时间。经过的数值表示动画已完成的时间的百分比,0的意思表示 动画进行了0%和1的意思表示动画进行100%。例如,在图1中,在T = 10毫秒的经过的分数将是0.25,因为总的持续时间是t = 40毫秒。
当ValueAnimator完成计算一个动画时长段,它调用当前设置的TimeInterpolator为计算后的间插值。间插值将所需的值映射到一个新的值作为间插值,即设置。例如,在图2中,因为动画慢慢加速,间插值为0.15,小于所经过的值0.25,在T = 10毫秒。在图1中,差值部分始终是相同的。
API 概述
你可以找到大部分的API android.animation属性动画系统。因为视图动画系统已经定义了多种插值算法在android.view.animation,你可以在属性动画系统使用插值以及。下面的表格描述了属性动画系统的主要组件。
Animators提供了用于创建动画的基本结构。你通常不直接使用这个类,它只提供最低限度的功能,必须扩展到完全支持动画。下面的子类扩展的动画类:
Table 1. Animators
- ValueAnimator
属性动画的主要时序引擎,该引擎还计算属性的值为动画的值。它拥有所有的核心功能,计算动画值,并包含每个动画的时间细节,是否有一个动画重复的信息,接收更新事件的侦听器,以及设置自定义类型的能力来评估。有两片动画属性:计算值和设定值的动画的对象和属性,正在动画。ValueAnimator不进行第二片,所以你必须听由ValueAnimator计算值的更新和修改的对象,你要有你自己的逻辑。 - ObjectAnimator
ValueAnimator的子类, 允许你设定一个目标对象和对象属性的动画。当它为动画计算一个新值时,该类相应地更新属性。大部分时间使用ObjectAnimator来做属性动画的更新,因为它使用更容易。然而,有时你想直接使用ValueAnimator,因为它更灵活。而ObjectAnimator则有较多一点的限制。 - AnimatorSet
提供一种机制,使一组动画一起运行,以便它们相互运行。您可以设置动画一起播放,顺序,或在指定的延迟后。
Evaluators告诉属性动画系统如何计算属性值。他们是由动画类提供的时序数据,动画的开始和结束值,并计算动画数据变化在这个数据基础上。属性动画系统提供以下Evaluators:
Table 2. Evaluators
- IntEvaluator
属性动画默认用来计算Int值 - FloatEvaluator
属性动画默认用来计算Float值 - ArgbEvaluator
属性动画默认用来计算颜色的十六进制值值 - TypeEvaluator
一个接口,允许你创建自己的计算器。如果你是动画的对象属性是不是int,float,或颜色,你必须实现的TypeEvaluator接口指定如何计算对象属性值的动画。你也可以指定一个int,自定义的TypeEvaluator浮动,和颜色的值,如果你想处理这些类型不同的默认行为。
插补器(interpolator )定义了一个动画中的特定值作为时间的函数的计算。例如,您可以指定在整个动画过程中线性的动画,使动画在整个时间内均匀地移动,或者你可以指定要使用的非线性的动画,加速开始,减速结束动画时。
Table 3.插补器 Interpolators
- AccelerateDecelerateInterpolator
其变化率开始和结束缓慢而在中间加速。
- AccelerateInterpolator
其变化率开始缓慢,然后加快。
- AnticipateInterpolator
刚开始向后。然后向前滑动。
- AnticipateOvershootInterpolator
刚开始向后,然后超过原来的值,最后返回到最后的值。
- BounceInterpolator
值到最后会回弹。
- CycleInterpolator
重复指定的次数。
- DecelerateInterpolator
其变化率开始快,然后减速。
- LinearInterpolator
变化率不远,匀速。
- OvershootInterpolator
值的变化将超过起始值和最后值,然后回来。
- TimeInterpolator
一个接口,允许你实现你自己的插补值。
使用ValueAnimator
ValueAnimator类允许你通过指定一组int,float,或色彩值来创建动画。你调用它的一个工厂方法:ofint(),offloat(),或ofobject()来得到一个ValueAnimator。例如:
ValueAnimator animation = ValueAnimator.ofFloat(0f, 1f);
animation.setDuration(1000);animation.start();
在这段代码中,start()方法运行时,在时间为1000毫秒期间,ValueAnimator开始在0和1之间计算动画的值。
您还可以通过以下方式指定一个自定义类型来动画:
ValueAnimator animation = ValueAnimator.ofObject(new MyTypeEvaluator(), startPropertyValue, endPropertyValue);
animation.setDuration(1000);
animation.start();
使用ObjectAnimator
objectanimator 是ValueAnimator子类,直接利用ValueAnimator值来更新对象的属性值。这使得动画物体容易得多,因为你不再需要实施valueanimator.animator updatelistener,因为动画属性会根据你的设定的值自动更新。
ObjectAnimator anim = ObjectAnimator.ofFloat(foo, "alpha", 0f, 1f);
anim.setDuration(1000);
anim.start();
想要正确的使用objectanimator更新属性,你必须做到以下几点:
objectanimator 更新 动画的对象属性必须有一个setter函数的形式设置属性名。因为objectanimator依赖setter函数来自动更新动画,它必须能够与这个setter方法访问属性。例如,如果属性名为foo,你需要有一个setfoo()方法。如果这个setter方法是不存在的,你有三个选择:
添加setter方法的类如果你有这样做的权利。
使用包装类,你必须改变和有包装获得有效的setter方法,拿到了它原来的对象权限。
使用ValueAnimator。
在其中的一个objectanimator工厂方法的参数, 如果只指定的一个 value… ,它被认为是动画的结束值。因此,在你的动画对象的属性必须有一个getter函数用于获取动画的起始值。getter函数必须在形式上get
()。例如,如果属性名为foo,你需要有一个getfoo()方法。 -
getter(如果需要)和setter方法的动画的属性必须使用相同类型的开始和结束值指定ObjectAnimator。例如,你必须targetObject.setPropName(float)和targetObject.getPropName(float) 如果你构建以下ObjectAnimator:
ObjectAnimator.ofFloat(targetObject, "propName", 1f)
取决于属性或对象动画,您可能需要调用invalidate()方法在视图迫使屏幕重绘与更新的动画本身的值。你这样做在onAnimationUpdate()回调。
用AnimatorSet编排多个动画
在很多情况下,你想开始一个动画,这取决于当另一个动画开始或结束。Android系统让你动画捆绑为一个AnimatorSet,这样你就可以同时指定是否开始动画,顺序,或在指定的延迟。
Plays bounceAnim.
同时 Plays squashAnim1, squashAnim2, stretchAnim1, and stretchAnim2。
Plays bounceBackAnim
-
Plays fadeAnim
AnimatorSet bouncer = new AnimatorSet(); bouncer.play(bounceAnim).before(squashAnim1); bouncer.play(squashAnim1).with(squashAnim2); bouncer.play(squashAnim1).with(stretchAnim1); bouncer.play(squashAnim1).with(stretchAnim2); bouncer.play(bounceBackAnim).after(stretchAnim2); ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f); fadeAnim.setDuration(250); AnimatorSet animatorSet = new AnimatorSet(); animatorSet.play(bouncer).before(fadeAnim);animatorSet.start();
动画监听器
Animator.AnimatorListener
onAnimationStart()
在动画开始被调用onAnimationEnd()
在动画结束被调用onAnimationRepeat()
当动画重复自己时候被调用onAnimationCancel()
当动画被取消的时候调用onAnimationEnd()
无论动画如何被取消,动画都会被调用ValueAnimator.AnimatorUpdateListener
onAnimationUpdate()
每一帧的动画都会被调用。在一个动画监听这个事件获取ValueAnimator生成的计算值。查询ValueAnimator对象传递到事件与getAnimatedValue获取当前动画值()方法来获取。实现此侦听器必需是使用ValueAnimator动画。
对于某些动画,您可能需要调用invalidate()来重新更新视图与新动画本身的值。例如,setAlpha()
,setTranslationX()。
使用动画
属性动画通过在屏幕上通过改变实际的属性来改变View。此外,View还自动调用invalidate()方法来刷新屏幕在其属性被更改时。视图类的新属性,促进属性动画:
ranslationX translationY:这些属性控制视图在父布局的左和上的位置。
rotation、rotationX rotationY:这些属性控制的2D旋转(rotation)和3D在轴心点的旋转(rotationX rotationY)。
scaleX 和 scaleY: 这些属性控制的2d围绕其轴心点的缩放视图。
pivotX 和 pivotY: 这些属性控制枢轴点的位置,旋转和缩放变换发生。默认情况下,枢轴点位于中心的对象。
x 和 y : 描述视图在父布局中最终位置,是 left和top的对应 translationX translationY 的总和。
-
alpha: 代表了alpha透明度视图。这个值是1(不透明的)默认情况下,用一个值0表示完全透明(不可见)。
ObjectAnimator.ofFloat(myView, "rotation", 0f, 360f);
使用插值器
interpolator 定义特定的值如何计算作为时间的函数。例如,您可以指定在整个动画动画发生线性,这意味着动画动作均匀,或您可以指定动画使用非线性时间,例如,使用加速或减速的开始或者结束动画。在interpolator 系统接收来自动画的一小部分代表动画的运行时间。interpolator 修改这部分动画的值,并返回动画。
AccelerateDecelerateInterpolator
public float getInterpolation(float input) { return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;}
LinearInterpolator
public float getInterpolation(float input) { return input;}
从XML使用动画
属性动画系统允许您声明属性动画使用XML而不是做编程。通过定义你的动画在XML中,可以很容易地重用你的动画更容易在多个活动和编辑动画序列。
区分动画文件使用新的属性动画api从那些使用传统视图动画框架,从Android 3.1开始,你应该保存XML文件属性动画在res/animator/(而不是res/anim/)。使用 animator 名称是可选的,但必要的如果你想要使用的布局编辑器工具在Eclipse ADT插件(ADT 11.0.0 +), 因为ADT只搜索res/animator/ 属性动画资源。
以下属性动画类XML声明支持以下XML标记:
ValueAnimator
ObjectAnimator
AnimatorSet
下面的例子中两组对象动画顺序,第一个嵌套组开始两个对象的动画:
为了运行这个动画,必须增加代码中的XML资源AnimatorSet对象,然后设置目标对象的所有动画在动画开始前集。调用setTarget()设置一个目标对象的所有子AnimatorSet。
AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext, R.anim.property_animator);
set.setTarget(myObject);
set.start();