Android Animation简述

一、动画(Animation
         Android框架提供了两种动画系统:属性动画(Android3.0)和视图动画。同时使用两种动画是可行的,但是一般首选使用属性动画,因为它更灵活、提供更多功能。除了这两种动画,你也可使用绘制动画——允许你加载drawable 资源并逐帧显示。
         视图动画只能用于View对象,所以如果你想要实现非View对象的动画,你必须用自己的代码去实现。实际上,视图动画仍是有局限性的,只能实现View的部分动画。例如,你可以实现View的缩放、旋转,但是背景颜色就不行了。
         另外一个视图动画不利的方面是,它只能改变View在哪儿绘制而不是真实的View 本身。举例来说,如果你使得一个按钮移动过屏幕,按钮被正确的绘制了,但你点击按钮实际上的位置并没有改变,所以你必须实现自己的逻辑来处理这个问题。
         而属性动画,不再有这些局限性,你可以使得任何物体(View和非View)的属性成为动画,并且对象本身也真正得改变。属性动画也使得产生动画的方式更健全了。在高版本,你可以将动画应用于各种属性,如颜色、位置或者大小,并能够定义动画的更多方面,如多个动画的穿插和同步。
         无论如何,实现视图动画只需要花费更少的时间和代码。如果视图动画能够完成你想要的效果,或者你当前的代码已如你所愿的工作,就没必要去使用属性动画了。你也可以考虑在不同的情况下分别使用这两种动画系统。
 

属性动画Property Animation

         Android 3.0中采用(API Level 11),属性动画使得你能改变任何对象的属性产生动画,包括未在屏幕上渲染的对象。这个系统是可扩展的,也能够应用于自定义类型的属性。

视图动画View Animation

         视图动画是较早的系统,并且只能用在View上。它相对简单并提供有足够的性能大多应用的需要。

绘制动画Drawable Animation

         绘制动画用于Drawable 资源一帧帧显示,类似电影。如果你想简单的用Drawable 资源展现东西,可以用这个动画方式,例如表现一序列的bitmaps。
 
         翻译自:官方SDK文档(参阅内容1)。
 

二、属性动画(Property Animation

         属性动画系统是一个允许你制作几乎所有动画效果的健全框架。你能够随时定义一个动画改变任何物体的属性,并且不必管它是否绘制在屏幕上。一个属性动画在一个指定的长度时间内改变一个属性(对象的字段)值。生成某物的动画,你需要指定你想要产生动画的对象属性,例如对象在屏幕的位置、动画持续的时间、属性值的变化范围等。
         属性动画系统可让你定义如下的动画特征:
         ·持续时间:你能够指定动画的持续时间。默认为300毫秒。
         ·时间变换:你能够指定属性是如何计算的,作为动画当前经过时间的一个方法。
         ·重复次数和行为:你能够指定在动画结束后是否重复以及重复的次数。你也能指定是否反向播放动画。或者设定重复进行正向播放继而反向,直到达到重复次数。
         ·动画者设定:你能够逻辑地组织动画,使得同时播放、顺序播放或者指定延迟播放。
         ·帧刷新延迟:你能够指定你动画的刷新频率。默认为每10毫秒,但是应用刷新帧的速率最终还是依赖于系统整体的忙碌度和其能够响应底层定时器的速度。
 
属性动画如何工作
         首先,让我们来看下动画如何工作的一个简单例子。图1描绘了一个x属性动画的假想物体,x属性用于表现它在屏幕的水平位置。动画的持续时间40毫秒,移动距离40像素。每10毫秒,默认的帧刷新速率,物体水平移动10像素。在40毫秒后,动画结束,物体停止在水平位置40处。这是一个线性插值的动画例子,意味着物体以恒定速度移动。
animation-linear.png
图1 线性动画例子
         你也能够指定非线性插值的动画。图2演示了一个假想的物体,在动画开始时加速,结束时减速。物体仍是40毫秒移动了40像素,但不是线性的。在开始时动画加速移动至中点,之后减速直到动画结束。如图2显示,在动画开始和结束位置的移动距离短于中间位置。
animation-linear.png
图2 非线性动画例子
         让我们详细的看下属性动画的重要构件是如何计算动画的,如上述演示的例子。图3描绘了主要类间的关系。
animation-linear.png
图3 动画如何计算的
         ValueAnimator对象保持动画时间的追踪,例如动画运行了多久,当前动画中的属性值。ValueAnimator封装了一个定义动画插值器的TimeInterpolator和一个定义如何计算动画属性值的TypeEvaluator。例如在图2中,使用的TimeInterpolatorAccelerateDecelerateInterpolator,而TypeEvaluatorIntEvaluator
         开始一个动画,要创建一个ValueAnimator 并给定好其开始和结束值,你想要随着时间动画的属性的值。当你调用start()时开始动画。在整个动画过程中,ValueAnimator由动画时间和逝去时间计算着一个0-1的逝去分数。逝去分数表示动画完成的时间百分比。0表示0%,1表示100%。例如在图1中,在10毫秒是逝去分数为0.25,因为总时间是40毫秒。
         当ValueAnimator完成了逝去分数的计算后,会调用当前设定的TimeInterpolator来计算插值分数。插值分数和逝去分数会匹配得到一个新的分数,并带入到设定的时间插值器中。例如,在图2中,因为动画的缓慢加速,在10毫秒时,插值分数大约0.15,小于逝去分数0.25。在图1中,插值分数则一直等于逝去分数。
         当插值分数计算后,ValueAnimator会调用合适的TypeEvaluator,通过插值分数、开始值和结束值来计算当前动画中的属性值。例如在图2中,插值分数在10毫时为0.15,所以当时的属性值为0.15x(40-0),为6。

         在API Demos样例工程的com.example.android.apis.animation包内提供了许多使用属性动画的例子。

 
API概览
         你能够在android.animation中找到最多的属性动画APIs。因为视图动画已经定义了许多插值器,android.view.animation内,你在属性动画中也能够使用这些插值器。接下来的表格描述了属性动画的主要组件。
         Animator类提供了创建动画的基础结构。你正常不会直接用这个类,因为它只提供了极少的功能,必须被继承来完全支持动画值。继承Animator的子类如下:
表1 Animators(动画者)
Class
Description

属性动画主要的计时器,也计算动画后的属性的值。它有所有核心的功能,包括计算动画值并包含每个动画的计时详细,动画是否重复的信息,接收更新事件的监听者,以及能够设置自定义的类型来赋值。它分为两部分来实现属性动画:计算动画值和设置这些值到动画中的对象和属性。ValueAnimator不实现第二部分,所以你必须监听来更新ValueAnimator计算的值,并用你自己的逻辑来修改你想动画的对象。更多信息请看Animating with ValueAnimator小节。

ValueAnimator的一个子类,允许你设置一个目标对象和对象的属性进行动画。当这个类计算好一个动画的新值后,相应的会更新其属性。大多数时候你都会想用ObjectAnimator,因为它使得动画值到目标对象的处理更简单了。无论如何,你有时也会想直接用ValueAnimator,因为ObjectAnimator有更多些的约束,比如需要指定acessor方法呈现在目标对象上。

提供组织动画的结构,使它们能相关联得运行。你能够设置动画一起播放,顺序播放或者指定延迟播放。更多信息请看Choreographing multiple animations with Animator Sets小节。

         Evaluators 告诉了属性动画系统如何计算给出属性的值。它们获得Animator类提供的计时数据,动画开始和结束的值,同时由这些数据计算出属性动画后的值。属性动画系统提供了如下的Evaluators :
表2 Evaluators(计算器)
Class/Interface
Description
计算int属性值的默认计算器
计算float属性值的默认计算器
计算color属性值的默认计算器,其中color属性以16进制表示

一个允许你创建自己的计算器的接口。如果要动画的对象属性不是int,float或颜色,你必须实现TypeEvaluator接口来指定如何计算对象属性的动画值。你也能够为int,float和color指定一个自定义的TypeEvaluator,如果想要不同于默认习性的方式处理这些类型。关于如何写一个自定义的计算器的更多信息,请看Using a TypeEvaluator小节。

 

         一个时间内插器作为时间的方法,定义了动画中具体的值如何计算。举例来说,你能够指明动画在整个过程中线性发生的,意味着动画在整个时间内平衡地进行;或者你能够指明动画使用非线性的时间,举例来说,在开始加速并在结束减速。表格3描述了在android.view.animation中的内插器。如果没有一个提供的内插器适合你的需要,可以继承TimeInterpolator接口,创建你自己的内插器。如何写一个自定义的内插器的更多信息,请看Using interpolators 小节。

表3 Interpolators(内插器)
Class/Interface
Description
变化速率开始和结束很慢但加速通过了中间
变化速率开始非常的慢,然后加速
变化开始向后,继而猛冲向前
变化开始向后,猛冲向前并超过目标值,继而最终返回至结束值
变化在结束时弹跳
动画重复一个指定的循环次数
变化速率开始时非常的快,然后减速
变化速率是一个恒量
变化急冲向前并超过目标值,然后返回
允许你实现自己内插器的一个接口
 
使用ValueAnimator产生动画
         ValueAnimator类使得你能够通过指定int,float或color值来产生这些类型的动画。你可以通过调研它的工厂方法: ofInt()ofFloat()ofObject(),而获得ValueAnimator。例如:
  1. ValueAnimator animation = ValueAnimator.ofFloat(0f, 1f); 
  2. animation.setDuration(1000); 
  3. animation.start(); 
         在这段代码中,当start()方法运行,ValueAnimator即开始计算动画的值。范围0到1,持续时间1000ms。
         你也可以通过如下方式,指定一个自定义类型来进行动画:
  1. ValueAnimator animation = ValueAnimator.ofObject(new MyTypeEvaluator(), startPropertyValue, endPropertyValue); 
  2. animation.setDuration(1000); 
  3. animation.start(); 
         在这段代码中,当start() 方法运行,ValueAnimator即开始计算动画的值。范围在用MyTypeEvaluator提供的逻辑的startPropertyValue到endPropertyValue间,持续时间1000ms。

         无论如何,先前的代码片段没有真正影响到对象,因为ValueAnimator不直接操作对象或属性。你想要做的最可能的事是用这些计算过的值来改变对象。你通过在ValueAnimator内定义监听者,来适当地处理动画生命期里的重要事件,如帧刷新。当实现了监听者,你能够通过调用getAnimatedValue()来获得计算过的值,用于具体的帧刷新。关于监听者的更多信息,请看Animation Listeners小节。

 
使用ObjectAnimator产生动画
ObjectAnimatorValueAnimator的一个子类(在先前的小节中讨论过),并联合了计时器和ValueAnimator的值计算,拥有为目标对象产生命名属性的动画的能力。这使得制作任何一个对象的动画更简单,例如你不再需要实现ValueAnimator.AnimatorUpdateListener接口,因为动画属性将会自动更新。
         实例化一个ObjectAnimator类似于ValueAnimator,但你还要指明对象和对象属性的名字(String型)以及动画的范围值。
  1. ObjectAnimator anim = ObjectAnimator.ofFloat(foo, "alpha", 0f, 1f); 
  2. anim.setDuration(1000); 
  3. anim.start(); 
         为了使得ObjectAnimator正确地更新属性,你必须如下操作:
         ·你动画的对象属性必须有一个set<propertyName>()形式的setter方法(驼峰式)。因为ObjectAnimator在动画期间自动更新属性,它必需能够用setter方法访问属性。例如,如果属性名称是foo,你必须有一个setFoo()的方法。如果这个setter方法不存在,你有3种选择:

         1. 如果你有权利这么做的话,给该类加上setter方法。

         2. 用一个你有权力更改的封装类,同时使得该封装类通过一个正确地setter方法接收值并传递给原先的对象。

         3. 用ValueAnimator代替。

         ·如果你只为ObjectAnimator某一工厂方法的values…参数指明了一个值,它将会被认为是动画的结束值。因此,你动画的对象属性必须有一个getter方法用来获得动画的开始值。getter方法必须是get<propertyName>()形式。例如,如果属性名称是foo,你需要有一个getFoo()的方法。
         ·你动画属性的getter(如果需要的话)和setter方法,必须操作相同的类型作为你指定给ObjectAnimator的开始和结束值。例如,如果你构造如下的ObjectAnimator,你必须有targetObject.setPropName(float)和targetObject.getPropName(float)方法:
  1. ObjectAnimator.ofFloat(targetObject, "propName", 1f) 

         ·根据你动画的属性或物体,你可能需要在View内调用invalidate()方法强行用更新后的动画值重绘屏幕。你可以在onAnimationUpdate()回调里做这个操作。例如,产生Drawable对象的颜色属性值动画,当对象重绘自己时引起的屏幕更新。所有View上的属性setters方法,例如setAlpha()setTranslationX()会适当地使视图无效,所以当你调用这些方法设置新值时不需要再使视图无效。关于监听者的更多信息,请看Animation Listeners小节。

 
使用AnimatorSet设计复合动画
         在许多情况下,你想要一个动画在另一个动画开始或者结束时开始进行。Android系统让你捆绑动画一起到一个AnimatorSet,这样之后你就能够指定是否同时开始动画,还是顺序地或者在指定延迟后。你也可以互相套入AnimatorSet对象。

         如下的样例代码是从Bouncing Balls例子中取出的(修改简单了),它以如下方式进行了Animator对象。

1. Plays bounceAnim.

2. Plays squashAnim1, squashAnim2, stretchAnim1, and stretchAnim2 at the same time.

3. Plays bounceBackAnim.
4. Plays fadeAnim.
 
  1. AnimatorSet bouncer = new AnimatorSet(); 
  2. bouncer.play(bounceAnim).before(squashAnim1); 
  3. bouncer.play(squashAnim1).with(squashAnim2); 
  4. bouncer.play(squashAnim1).with(stretchAnim1); 
  5. bouncer.play(squashAnim1).with(stretchAnim2); 
  6. bouncer.play(bounceBackAnim).after(stretchAnim2); 
  7. ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f); 
  8. fadeAnim.setDuration(250); 
  9. AnimatorSet animatorSet = new AnimatorSet(); 
  10. animatorSet.play(bouncer).before(fadeAnim); 
  11. animatorSet.start(); 

         关于如何使用动画者集合的更完整的例子,请看API Demos中Bouncing Balls样例。

 
动画监听者
         使用如下描述的监听者,你能够监听在整个动画过程中重要的事件。
         ·Animator.AnimatorListener

         ·onAnimationStart() – 当动画开始时调用

         ·onAnimationEnd() – 当动画结束时调用

         ·onAnimationRepeat() – 当动画重复时调用

         ·onAnimationCancel()  - 当动画取消时调用。一个被取消的动画也会调用onAnimationEnd(),无论它是如何停止的。

         ·onAnimationUpdate() – 在动画的每一帧调用。监听这个事件来使用在动画期间由ValueAnimator 生成的计算值。使用这个值,查询传入事件的ValueAnimator 对象再由getAnimatedValue() 方法得到当前动画的值。如果你用ValueAnimator,这个监听者是被要求实现的。

         依赖于你动画的是什么属性或对象,你可能需要在View上调用invalidate()来强行使得屏幕区域用动画后的值重绘自己。例如,产生Drawable对象的颜色属性值动画,当对象重绘自己时引起的屏幕更新。所有View上的属性setters方法,例如setAlpha()setTranslationX()会适当地使视图无效,所以当你调用这些方法设置新值时不需要再使视图无效。

         例如,在API Demos中Bouncing Balls样例创建了一个AnimatorListenerAdapter 用于onAnimationEnd()回调:

  1. ValueAnimatorAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f); 
  2. fadeAnim.setDuration(250); 
  3. fadeAnim.addListener(new AnimatorListenerAdapter() { 
  4. public void onAnimationEnd(Animator animation) { 
  5.     balls.remove(((ObjectAnimator)animation).getTarget()); 
 
产生ViewGroups布局变化动画
         属性动画除了提供了View动画的一种简单方式,还提供了ViewGroup 对象动画的能力。
         你能够用LayoutTransition 类在ViewGroup内产生布局变化动画。在ViewGroup内的视图,当你移除它们或者调用View的setVisibility() 方法设置VISIBLEGONE时,能够产生出现和消失的动画。剩余ViewGroup内的视图,在你增加或删除视图时,也能够移动它们新的位置。你能够通过调用setAnimator()并用如下的LayoutTransition某一常数传入Animator对象,在一个LayoutTransition 对象内定义如下的动画:
·APPEARING  - 一个指示在容器内出现项目的动画标记。
·CHANGE_APPEARING – 一个指示在容器内由于出现新项目而产生变化的动画标记。
·DISAPPEARING – 一个指示在容器内项目消失的动画标记。
·CHANGE_DISAPPEARING – 一个指示在容器内由于一个项目消失而产生变化的动画标记。
         你可以为这四种事件类型定义自己的动画来设置你布局过渡的效果或者只是告诉动画系统采用默认动画。
         在API Demos的LayoutAnimations样例,展示了如何为布局过渡定义动画和之后设置你想要动画的View对象的动画。
         LayoutAnimationsByDefault和它一致的layout_animations_by_default.xml布局资源文件展示了如何在XML中为你的ViewGroups启用默认的布局过渡。你需要做的唯一一件事为ViewGroup设置android:animateLayoutchanges属性为true。例如:
  1. <LinearLayout 
  2.     android:orientation="vertical" 
  3.     android:layout_width="wrap_content" 
  4.     android:layout_height="match_parent" 
  5.     android:id="@+id/verticalContainer" 
  6.     android:animateLayoutChanges="true" /> 
         设置这个属性为true后,将自动动画GroupView增加或移除视图以及ViewGroup剩余的视图。
 
使用类型计算器(TypeEvaluator
         如果你想要产生Android系统未知类型的动画,你必须通过实现TypeEvaluator接口来创建你自己的计算器。Android系统知道的类型是int,float或color,各自由IntEvaluatorFloatEvaluatorArgbEvaluator类型计算器支持。
         在TypeEvaluator接口内要实现的方法只有一个evaluate()方法。这允许了你正使用的动画者,能够为你在动画当前点的动画属性,返回一个合适的值。FloatEvaluator类演示了如何做这些:
  1. public class FloatEvaluator implements TypeEvaluator { 
  2.  
  3.     public Object evaluate(float fraction, Object startValue, Object endValue) { 
  4.         float startFloat = ((Number) startValue).floatValue(); 
  5.         return startFloat + fraction * (((Number) endValue).floatValue() - startFloat); 
  6.     } 
         注意:当ValueAnimator(或ObjectAnimator)运行,它先计算出一个动画当前逝去分数(0到1之间的值),然后依靠你正使用的内插器计算出一个插值版本。插值分数是你的TypeEvaluator通过fraction参数得到的, 所以在计算动画后的值时你不一定要把它带入给内插器。
 
使用内插器(Interpolators
         内插器作为时间的方法,定义了动画中具体的值如何计算。举例来说,你能够指明动画在整个过程中线性发生的,意味着动画在整个时间内平衡地进行;或者你能够指明动画使用非线性的时间,举例来说,在开始加速并在结束减速。

         在动画系统中内插器从动画者那接收表现动画逝去时间的分数。内插器修改这个分数,同时变为它打算提供的动画类型。Android系统在android.view.animation package提供了一套公共的内插器。如果没有一个适合你的需要,你可以实现TimeInterpolator 接口来创造自己的内插器。

         作为例子,默认内插器AccelerateDecelerateInterpolatorLinearInterpolator如何计算内插分数在下面进行了比较。LinearInterpolator没影响到逝去分数。而AccelerateDecelerateInterpolator加速进入动画并减速退出。下面的方法定义了这两个的逻辑:
AccelerateDecelerateInterpolator
  1. public float getInterpolation(float input) { 
  2.     return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f; 
LinearInterpolator
  1. public float getInterpolation(float input) { 
  2.     return input; 
         下面的表格表现了在动画1000毫秒内这两内插器计算得的近似值:
ms elapsed

Elapsed fraction/Interpolated fraction (Linear)

Interpolated fraction (Accelerate/Decelerate)

0
0
0
200
0.2
0.1
400
0.4
0.345
600
0.6
0.8
800
0.8
0.9
1000
1
1
         正如表格显示的,LinearInterpolator以同样的速度改变值,每过200ms增加0.2。而AccelerateDecelerateInterpolator改变值比起LinearInterpolator,在200ms到600ms内快、在600ms到1000ms慢。
 
指明关键帧(Keyframe
         Keyframe对象由time/value对组成,让你在动画具体的时间定义具体的状态。每个关键帧也可以有它自己的内插器来控制从前一个关键帧时间至当前关键帧时间的间断内的动画的行为。
         实例化Keyframe对象,你必须用ofInt()、 ofFloat()ofObject()中某个工厂方法类获得Keyframe的适当类型。之后调用ofKeyframe()工厂方法来获得PropertyValuesHolder对象。一旦你有了该对象,你能够通过传入PropertyValuesHolder对象和动画的对象来获得一个动画者。以下的代码片段演示了如何使用它:
  1. Keyframe kf0 = Keyframe.ofFloat(0f, 0f); 
  2. Keyframe kf1 = Keyframe.ofFloat(.5f, 360f); 
  3. Keyframe kf2 = Keyframe.ofFloat(1f, 0f); 
  4. PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2); 
  5. ObjectAnimator rotationAnim = ObjectAnimator.ofPropertyValuesHolder(target, pvhRotation) 
  6. rotationAnim.setDuration(5000ms); 
         关于如何使用帧对象更复杂的例子,参见API Demos内MultiPropertyAnimation样例。
 
视图动画
         属性动画系统允许视图流线型的动画并提供了一些超越视图动画系统的优点。视图动画系统通过改变绘制方式来改变视图对象。这个是在每个视图容器内处理的,因为视图自身没有操作这些属性。这导致了在视图动画的过程中,并没有引起视图对象自身的改变。这致使了如对象一直存在它原来的位置,即使它被绘制在屏幕不同的区域的表现。在Android3.0,增加了新的属性和相应的getter和setter方法以消除这个不足。
         属性动画系统能够通过改变View对象真实的属性类在屏幕上产生视图动画。此外,视图无论何时属性发生改变也会自动调用invalidate()方法来刷新屏幕。在View 类中帮助属性动画的新属性是:
·translationX and translationY:这些属性控制视图位于哪里,由布局容器设置的它的左和顶坐标。
·rotation, rotationX, and rotationY:这些属性控制2D(rotation属性)中的旋转和3D围绕的支点。
·scaleX and scaleY:这些属性控制了视图围绕它支点的2D缩放。
·pivotX and pivotY:这些属性控制支点的位置,围绕它旋转和缩放变化发生。默认的,支点位于对象的中心。
·x and y:这些是简单的共用属性来描述视图在它容器内的最终位置,为left和top值和translationX和 translationY的值和。
·alpha:表现视图的alpha透明度。这个值默认为1(不透明),0表现为全透明(不可见)。
         动画视图对象的一个属性,例如它的颜色或旋转值,你所要做的是创建一个属性比哦啊沿着并指明你想要动画的视图属性。例如:
  1. ObjectAnimator.ofFloat(myView, "rotation", 0f, 360f); 
         关于创建动画者的更多信息,参见小节使用ValueAnimator产生动画及使用ObjectAnimator产生动画。
 
使用ViewPropertyAnimator产生动画
         ViewPropertyAnimator提供了一个简单的方式来类似地产生View一些属性的动画,使用一个单纯的下方的Animator对象。它表现非常像ObjectAnimator,因为它改变视图属性的真实值,但在动画许多属性时更加有效。此外,使用ViewPropertyAnimator的代码阅读起来更加简洁易懂。如下的代码片段展现了当同时的动画View的x和y属性时,用复合的ObjectAnimator对象,单个ObjectAnimator以及用ViewPropertyAnimator之间的差别。
·复合的ObjectAnimator对象
  1. ObjectAnimator animX = ObjectAnimator.ofFloat(myView, "x", 50f); 
  2. ObjectAnimator animY = ObjectAnimator.ofFloat(myView, "y", 100f); 
  3. AnimatorSet animSetXY = new AnimatorSet(); 
  4. animSetXY.playTogether(animX, animY); 
  5. animSetXY.start(); 
  1. PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("x", 50f); 
  2. PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("y", 100f); 
  3. ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvyY).start(); 
  1. myView.animate().x(50f).y(100f); 

         关于ViewPropertyAnimator更多的详细信息,参见相应的Android Developers blog post

 
用XML声明动画
         属性动画系统让你可以用XML声明属性动画而不必用程序实现。通过用XML定义你的动画,你能够简单的在多样的活动中复用动画,并能更简单地编辑动画的序列。

         为了区分动画文件是使用的新的属性动画APIs还是用的遗留的view animation框架,从Android3.1开始,你应当为属性动画的XML文件保存进res/animator/目录(而不是res/anim/)。使用的animator 目录名称是随意的,但如果你想要用在Eclipse ADT插件(ADT 11.0.0+)中的布局编辑器工具的话是必须的,因为ADT只查找res/animator/目录中的属性动画资源。

         以下的属性动画类名称需要有如下的XML标记来声明:
·ValueAnimator - <animator>
·ObjectAnimator - <objectAnimator>
·AnimatorSet - <set>
         如下的例子顺序播放两组对象动画,用第一个嵌套设置了同时播放两个对象动画:
  1. <set android:ordering="sequentially"> 
  2.     <set> 
  3.         <objectAnimator 
  4.             android:propertyName="x" 
  5.             android:duration="500" 
  6.             android:valueTo="400" 
  7.             android:valueType="intType"/> 
  8.         <objectAnimator 
  9.             android:propertyName="y" 
  10.             android:duration="500" 
  11.             android:valueTo="300" 
  12.             android:valueType="intType"/> 
  13.     </set> 
  14.     <objectAnimator 
  15.         android:propertyName="alpha" 
  16.         android:duration="500" 
  17.         android:valueTo="1f"/> 
  18. </set> 
         为了运行这个动画,你必须在代码中装载该XML资源进AnimatorSet对象,然后在开始动画组时为所有动画设置目标对象。调用setTarget()便利地为AnimatorSet的所有子动画设置一个目标对象。如下代码显示了如何做这个:
  1. AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext, 
  2.     R.anim.property_animator); 
  3. set.setTarget(myObject); 
  4. set.start(); 

         关于更多定义属性动画的XML语法信息,参见Animation Resources

 
         翻译自:官方SDK文档(参阅内容1)。
 
三、后记
1)参阅内容

1.1)SDK docs->Dev Guide->Framework Topics->Animation

 

1.2)SDK docs->Dev Guide->Application Resources->Resource Types->Animation