Property Animation(属性动画)

本文深入解析了Android中的属性动画系统,包括其工作原理、与视图动画的区别、API概述及使用方法。介绍了如何创建属性动画、使用AnimatorSet编排复合动画等高级技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概述

属性动画系统是一个强大的框架,它允许你将大多数东西动画化。你可以定义一个动画用来在动画播放的时候改变任何对象的属性值,而不管它在屏幕上有没有被绘制。属性动画在指定长度的时间内改变一个属性(对象的一个字段)的值。开始动画化一些东西,由你指定你想要动画化的对象属性,如一个在屏幕上的对象的属性,指定动画播放的时长,和在动画时改变成什么值。
属性动画系统会指导你如何去定义一个动画,只需要遵循如下步骤:
  • 持续时间:可以指定动画的持续时间,默认是300 ms 
  • 时间插值:可以在动画运行时通过一个函数来指定需要改变的属性值多久计算一次。
  • 重复次数和行为:当动画播放到末尾时,可以指定是否重复播放以及播放的次数。你还可以指定动画是否倒着播放。设置反向播放动画反复向前然后向后,直到达到重复出现的次数。
  • 动画设置:可以对动画进行逻辑分组,一起播放或顺序播放或指定延迟播放。
  • 帧刷新延迟:可以指定动画帧的刷新频率。默认值是每10ms 刷新一次,但是最终的刷新速度取决于你系统整体的繁忙度和响应时间。

 属性动画工作原理

首先,让我们通过一个简单的例子来了解动画是如何工作的。图1描述了一个假设的对象对它的x属性进行动画化,即它在屏幕上的水平位置。动画的持续时间设置为40ms 并且x增大了40像素。每10ms ,即默认帧刷新时间,该对象的水平距离就移动10像素。到最后的40ms时,动画停止,此时该对象的水平距离是40。这就是一个带有线性插值的动画,意味着该对象以一个恒定速度移动了。

图1.线性动画示例

你也可以将它设置为非线性的。图2说明了一个假想的对象在动画的前一段时间内加速,后一段时间内减速 的动画效果。该对象依旧是在40ms 中移动了40像素,但并非线性的。开始的一段时间,该动画加速至一半的点(即X=20),然后从这点开始减速,直到最后。如图2所示,开始和结束时移动的距离小于中间。

图2.非线性动画示例

让我们详细的看看属性动画系统的重要组件是如何像上面一样计算动画的。图3描述了主要的类是如何与其他类工作的。

图3.动画是如何计算的

ValueAnimator  对象在动画期间持续跟踪,如动画已经运行了多长时间,和当前动画的属性值。
ValueAnimator  封装了一个 TimeInterpolator,被用来定义补间动画,还有一个 TypeEvaluator ,被用来定义动画开始后的属性值。例如,在图2, TimeInterpolator  将会使用   AccelerateDecelerateInterpolator  ,而   TypeEvaluator 将会使用   IntEvaluator .。
开始一个动画,创建一个   ValueAnimator   并且给它你想要动画化属性开始和结束的值,随着动画的进行。当调用 start(),动画开始播放。在动画播放的整个时间段内, ValueAnimator  计算一个在0和1之间的已播放分数( elapsed fraction ),基于持续时间和已播放时间。这个已播放分数代表着动画播放完成时间的百分百,0意味着0%,1意味着100%。例如,在图1,在t=10ms时的已播放分数是0.25因为总的持续时间是40ms 。
  ValueAnimator  计算完成了一个已播放分数,就会调用刚才设置的   TimeInterpolator  来计算插值分数( interpolated fraction )。一个插值分数将已播放分数映射到一个新的需要考虑时间插值的分数。例如,图2中,因为动画是逐渐加速的,在t=10ms 时,它的插值分数,大约是0.15,小于此时的已播放分数0.15。在图1,插值分数永远等于已播放分数。
当插值分数计算完成, ValueAnimator  调用适当的   TypeEvaluator ,来计算你需要动画化的属性的值,基于插值分数,开始值和结束值。例如,在图2中,t =10ms 时的插值分数是0.15,所以此时的属性值将会是0.15x (40 - 0),或者6。
com.example.android.apis.animation  包下的   API Demos 有许多关于如何使用属性动画系统的例子。

属性动画与视图动画的不同之处

视图动画系统仅仅提供了动画化view对象的能力,因此如果你想要动画化非view对象,只能由你自己去编码实现了。视图动画系统也是受限制的,因为它只公开了几个方面的动画视图对象,如对view的缩放和旋转,而没有背景颜色。
视图动画的另一个缺点是它只在View绘制时修改视图,并非真正修改view本身。例如,如果你实现一个 让一个按钮从左至右穿过屏幕 这样的一个动画,按钮会正确的绘制,但是它的实际位置是没有变化的,你还是可以在原来的位置点击它,所有你必须实现自己的逻辑来处理这个问题。
而属性动画系统,这些约束完全被移除了,并且你可以动画化任何对象(view 和非view)的任何属性,对象本身也确实被修改了。属性动画系统也用更健壮的方式执行动画。在更高层次上,你可以为你想要动画化的属性,如颜色,位置,或大小, 分配动画师,并且可以定义动画的各个方面,如插值和多个画师同步。
视图动画系统,然而,花费更少的时间来设置,需要更少的代码编写。如果视图动画完成了你需要做的一切,或者如果你现有的代码已经按你所期望的方式工作了,那就不需要使用属性动画系统了。如果用例出现了不同的情况,使用动画系统也是十分有意义的。

API 概述

android.animation .中可以找到最多的关于属性动画系统的API相关知识。因为在   android.view.animation  中已经定义了许多视图动画系统的插入器,你可以在属性动画系统中使用这些插入器。接下来的几张表格展示了属性动画系统的主要组件。

Animator 类提供了创建动画的基础结构。一般情况下你不必直接使用该类,它仅提供最小的功能,因此你必须继承它用以完全支持动画值。下面的这些子类都继承自 Animator

Table 1. Animators

Class Description
ValueAnimator  属性动画的主要计时引擎,也经常计算动画时的属性值。它具有所有的核心功能——计算动画值和包含每个动画的时间细节, 有关于动画何时重复播放的信息, 接收更新事件的监听器, 设置自定义的估计(evaluate)类型. 它主要有两个功能: 计算动画的值和在动画时为对象设置这些值。ValueAnimator 并不执行第二个功能, 因此你必须通过监听. ValueAnimator 计算出来的值的更新事件 来用你自己的逻辑修改你想要动画的对象的值。查看 #使用ValueAnimator制作动画部分获取更多消息。
ObjectAnimator  ValueAnimator 的一个子类,允许你设置目标对象和需要动画化的属性。  该类根据动画计算出来的新值来更新属性值. 大多数时候你需要用到 ObjectAnimator , 因为它使动画值用在目标对象上更加容易。然而,有些时候你必须直接使用ValueAnimator 因为ObjectAnimator 有一些限制,例如在目标对象上请求特定的存取方法。
AnimatorSet 提供一个组织动画的途径,这样你可以让它们通过一个顺序运行。例如一起播放,顺序播放,或延迟播放. 查看#使用AnimatorSet编排复合动画 章节获取更多信息。

求值器(Evaluator )告诉属性动画系统如何计算给定属性的值。它们通过 Animator 类来获取提供的时间数据,动画开始和结束的值,并且基于这些值计算动画时的属性值。属性动画系统支持如下求值器:

Table 2. Evaluators

Class/Interface Description
IntEvaluator 计算int 属性的默认求值器
FloatEvaluator 计算float 属性的默认求值器
ArgbEvaluator 计算颜色属性的默认求值器,是一个十六进制的值
TypeEvaluator 一个允许你创建自己的求值器的接口。 如果你要计算的对象属性值不在int,float,或颜色之中,你必须实现 TypeEvaluator 接口来指定如何计算动画属性值。你也可以为int,float,color指定一个自定义的求值器,如果不你想用默认方法的处理这些类型。查看 #使用TypeEvaluator章节获取更多信息

时间插值器(time interpolator)定义了一个时间函数如何在动画时计算一个特定的值。例如,你可以指定动画在整个动画时是线性发生的,意味着在整个时间内动画移动是匀速的。或者你可以指定为非线性的,例如在开始时加速,结束时减速。表3描述了包含在android.view.animation.中的插值器。如果这之中没有你需要的,实现TimeInterpolator接口来创建你自己的。查看#使用插值(Interpolators)来获取更多关于如何自定义插值器的知识。

Table 3. Interpolators

Class/Interface Description
AccelerateDecelerateInterpolator 开始和结束时慢,中间快
AccelerateInterpolator 开始慢,然后加速
AnticipateInterpolator 开始向后,然后向前
AnticipateOvershootInterpolator 开始向后,甩向前并且冲过目标值,最终回到目标值
BounceInterpolator 最后反弹
CycleInterpolator 重复指定次数
DecelerateInterpolator 开始快,然后减速
LinearInterpolator 恒定不变速度
OvershootInterpolator 甩向前,冲过目标值,然后回来
TimeInterpolator 可以让你实现自动的插值器的一个接口

ValueAnimator  类可以在动画持续时间内 通过指定一组int,float 或color 值实现某些动画类型。通过调用它的工厂方法来获得 ValueAnimator  :   ofInt() ofFloat() , or  ofObject()  例如
   
ValueAnimator animation = ValueAnimator.ofFloat(0f, 1f);
animation.setDuration(1000);
animation.start();
代码中,当     start()方法开始运行时, ValueAnimator  开始计算动画值,介于0和1之间,持续时间是1000ms 。
你还可以为动画指定一个自定义类型,如下:
    
ValueAnimator animation = ValueAnimator.ofObject(new MyTypeEvaluator(), startPropertyValue, endPropertyValue);
animation.setDuration(1000);
animation.start();
代码中,当start ()方法开始运行时, ValueAnimator  开始计算动画值,介于 startPropertyValue  和  endPropertyValue  之间,使用由 MyTypeEvaluator  提供的逻辑,持续时间1000ms 。
上面的代码片段,是的,在一些对象上是没有有实际作用的,因为
ValueAnimator  并不直接操作对象或值。更有可能的方法是通过修改这些动画的计算值来修改对象。在 ValueAnimator  中定义一个监听器来处理动画期间的重要事件,如帧刷新。当实现了该监听器,你可以通过调用 getAnimatedValue() . 得到这一帧刷新时的计算值。更多关于这个监听器的知识,请看 #动画监听器
ObjectAnimator  是   ValueAnimator  的子类(在之前章节介绍过)并且结合了时序引擎和计算 ValueAnimator的目标对象动画化属性值的功能。这使得动画化任何对象变得容易,一如你不再需要实现   ValueAnimator.AnimatorUpdateListener 因为它的动画属性会自动更新。
实例化一个   ObjectAnimator  对象和实例化 ValueAnimator相似,但是你依然要指定对象和对象属性的名称(作为String )和两个动画值:
   
ObjectAnimator anim = ObjectAnimator.ofFloat(foo, "alpha", 0f, 1f);
anim.setDuration(1000);
anim.start();
为了让 ObjectAnimator  正确的更新,你必须做如下工作:
○    需要动画的对象属性必须要有函数形式为 set<propertyName>() setter函数。因为   ObjectAnimator  在动画时自动的更新属性,一定要通过这个setter函数来设置属性。例如,如果这个属性名为 foo ,你就必须要有一个 setFoo()  的方法。如果没有这样的setter 方法,你有三种选择:
  • 如果你有权利这么做,在类中加入这个setter方法。
  • 使用包装类,这样你就有权去更改这个包装类,并且该包装类通过setter函数获得有效的值,并将它转发给原来的对象。
  • 使用ValueAnimator 替代
    如果在   ObjectAnimator  的某一构造函数中, 你的 values...  参数中只有一个值,它将被假定为结束值。因此,动画对象的属性必须有一个getter函数用来获得动画开始时的开始值。这个getter函数必须是 get<propertyName>()形式的。 例如,如果属性名为 foo ,你必须有一个 getFoo() 的函数。
○    动画属性的getter 函数(如果需要)和setter 函数必须操作的是同一类型的由   ObjectAnimator 指定的 开始和结束值。例如,如果你构造了如下的   ObjectAnimator :,你必须有   targetObject.setPropName(float)  和 targetObject.getPropName(float):
  
ObjectAnimator.ofFloat(targetObject, "propName", 1f)
取决于你的动画属性和对象,当view显示在屏幕上时,你或许需要调用 invalidate()方法来重绘视图和更新动画值。在 onAnimationUpdate()回调函数中做这些事情。例如,为一个可绘制对象的颜色属性做动画,当这个对象重绘自己的时候才导致更新屏幕。所有view 上的设置,如 setAlpha()  和  setTranslationX()  直接无效了,所以当调用这些方法设置新值时,你不必无效化view。更多关于监听器的信息,请查看 #动画监听器
在许多情况下,你想要播放的动画取决于其它的动画开始或结束后。安卓系统使你可以在 AnimatorSet中将动画整合在一起,这样你就可以指定是否同时播放动画,顺序播放,或者延迟指定时间后播放。你也可以彼此嵌套(nest ) AnimatorSet  对象。
接下来的示例代码取自 Bouncing Balls  示例(简单的修改了)通过如下的方式播放了如下的 Animator  对象:
  1. Plays bounceAnim.
  2. Plays squashAnim1squashAnim2stretchAnim1, and stretchAnim2 同时播放
  3. Plays bounceBackAnim.
  4. 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();
更多关于如何使用动画集合的完整示例,请看API示例中的 Bouncing Balls  实例。
在动画持续时间内,你可以监听如下重要的事件。
  • Animator.AnimatorListener
  • ValueAnimator.AnimatorUpdateListener
    • onAnimationUpdate() - 动画的每一帧时调用. 在动画期间,通过监听该事件来使用 由ValueAnimator产生的 计算值。使用这一值,询问传递到该事件中的ValueAnimator 对象,通过getAnimatedValue() 来获取当前动画值。如果你使用了ValueAnimator 就需要实现这一监听器。

      取决于你的动画属性和对象,当view显示在屏幕上时,你或许需要调用invalidate()方法来重绘视图和更新动画值。在onAnimationUpdate()回调函数中做这些事情。例如,为一个可绘制对象的颜色属性做动画,当这个对象重绘自己的时候才导致更新屏幕。所有view 上的设置,如setAlpha() 和 setTranslationX() 直接无效了,所以当调用这些方法设置新值时,你不必无效化view。

你可以继承 AnimatorListenerAdapter 类而不是实现Animator.AnimatorListener接口,如果你不想实现Animator.AnimatorListener接口中的所有方法。AnimatorListenerAdapter 类提供了空的实现方法供你选择性的覆盖。

例如,在api示例中的Bouncing Balls 案例中,创建了一个AnimatorListenerAdapter,仅仅只是调用了 onAnimationEnd() :

     
ValueAnimatorAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f);
fadeAnim.setDuration(250);
fadeAnim.addListener(new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator animation) {
balls.remove(((ObjectAnimator)animation).getTarget());
}

为ViewGroups做布局改变动画

属性动画系统提供了对 ViewGroup  对象动画化的能力,使得像动画化View一样简单。
通过使用 LayoutTransition类你可以做一个布局改变时的动画。在 ViewGroup  中的View可以播放出现和消失动画,当你将它们添加或移除 ViewGroup  时,或者调用View的 setVisibility()  方法设置时。当你添加或移除View时, ViewGroup  中 其余的View也可以动画移动到新的位置。通过调用 LayoutTransition  的 setAnimator()  传递一个   Animator  对象和如下的一个 LayoutTransition  常量 ,来定义一个动画:
  • APPEARING - 一个标志,表明那些出现在容器中的项目的动画。
  • CHANGE_APPEARING - 表明那些由于新项目出现在容器中而需要改变的项目的动画
  • DISAPPEARING -表明那些从容器中消失的项目的动画
  • CHANGE_DISAPPEARING - 表明那些由于一个项目在容器中消失而需要改变的项目的动画,
你可以定义你自己的动画效果,由这四个类型的事件来定制你的布局过渡效果,或者直接告诉动画系统使用默认动画。
在api样例中的   LayoutAnimations  示例展示了如如何自定义一个布局过渡动画,然后在你想要动画化的View对象上使用它。
LayoutAnimationsByDefault  和相应的 layout_animations_by_default.xml  布局资源文件展示了如何在xml文件中启用默认的布局过渡。你需要做的唯一事情就是设置 ViewGroup中的   android:animateLayoutchanges  属性为   true  ,如下:
   
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:id="@+id/verticalContainer"
android:animateLayoutChanges="true" />
设置这个属性为真,会自动的动画视图, 当从这个 ViewGroup  中添加或移除视图时。添加/移除的项和剩下的项都有动画效果。
如果你想要动画化的类型在安卓系统中未知,你可以通过实现 TypeEvaluator  接口来创建自己的求值器。目前安卓系统可识别的类型是int,float 或一个颜色值,分别对应   IntEvaluator FloatEvaluator , 和 ArgbEvaluator  的类型求值器。
TypeEvaluator  接口中只有一个需要实现的方法, evaluate()方法。它允许动画师使用一个 在动画的确切时间点返回的适当的 动画属性值。   FloatEvaluator  类演示了如何做:
    
public class FloatEvaluator implements TypeEvaluator {
 
public Object evaluate(float fraction, Object startValue, Object endValue) {
float startFloat = ((Number) startValue).floatValue();
return startFloat + fraction * (((Number) endValue).floatValue() - startFloat);
}
}
注:当 ValueAnimator  (or  ObjectAnimator )运行时,为动画计算了一个确切的已运行分数(介于0-1之间的值),然后计算了一个插值,具体取决于你所使用的插值器。插值分数是你的 TypeEvaluator通过 fraction  参数收到的,所有在计算动画值时不需要考虑插值器。
一个插值定义了 如何在动画时计算具体值的一个 时间函数。例如,你可以指定动画在播放时是线性的,意味着动画在整个播放时间内是匀速运动的,或者可以指定为非线性的,例如在开始时加速,结束时减速。
动画系统中的插值器接收一个由动画师发来的分数,这个分数代表着动画已经播放的时间。插值器修改这个分数用以与提供的目标动画类型相一致。在 android.view.animation package .包下安卓系统提供了一组通用的插值器。如果这些都不适合你,可以实现 TimeInterpolator  接口来创建自己的插值器。
举个例子,比较默认的插值器   AccelerateDecelerateInterpolator  和 LinearInterpolator  是如何计算插值分数的。 LinearInterpolator  对已播放分数没有影响。 AccelerateDecelerateInterpolator 加速进入动画,减速出来。下面展示了他们的插值逻辑:
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;
}
下表展示了由这些插值器计算一个时长为1000ms的动画的近似值:
已播放
ms 
已播放分数/插值分数
(Linear)
插值分数
 (Accelerate/Decelerate)
0 0 0
200 .2 .1
400 .4 .345
600 .6 .8
800 .8 .9
1000 1 1
如表所示,   LinearInterpolator  以恒定速度改变值,每过200ms增长.2。 AccelerateDecelerateInterpolator  比   LinearInterpolator 改变值的速度,在200ms -600ms 的时候更快,在600ms -1000ms的时候更慢。

指定关键帧

关键帧对象由一个 时间/值 对组成,是由你指定的动画中的一个特定时间的状态。每一个关键帧都有自己的插值器来控制他们的动画行为,在前一个关键帧和这一个关键帧之间。
实例化一个   Keyframe  对象,你必须yonder其中的一个工厂方法, ofInt() ofFloat() , 或 ofObject()  来获得合适类型的 Keyframe。之后调用 ofKeyframe()  工厂方法来获得一个 PropertyValuesHolder  对象。一旦你有了该对象,你可以通过传递 该对象和目标动画对象 来获得一个动画制作者对象。像这样:
   
Keyframe kf0 = Keyframe.ofFloat(0f, 0f);
Keyframe kf1 = Keyframe.ofFloat(.5f, 360f);
Keyframe kf2 = Keyframe.ofFloat(1f, 0f);
PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2);
ObjectAnimator rotationAnim = ObjectAnimator.ofPropertyValuesHolder(target, pvhRotation)
rotationAnim.setDuration(5000ms);
更多关于如何使用关键帧的完整示例,请看API 案例中的   MultiPropertyAnimation  示例。

视图动画化

属性动画系统允许查看对象的流线型动画,并且在视图动画系统上提供了一些优势。视图动画系统通过改变它绘制的方式来变换view对象。由各个view容器处理,因为view本身没有属性可用来操作。这导致view可以被动画化,但是view本身不会有变化。这样就会有 一个对象仍然在原来的位置 的现象,尽管它被绘制在了屏幕的不同位置。在安卓3.0,新的属性和相应的getter &setter 方法被加入了,用以消除这一弊端。
属性动画系统可以通过改变view对象的实际值而在屏幕上动画化view。另外,当它的属性被改变时,views 经常自动的调用 invalidate()  方法来刷新屏幕。在View 类中新添加的属性如下:
  • translationX and translationY: 这些属性控制了View的位置,作为它左部和上部坐标的增量,由布局容器设置。平移
  • rotationrotationX, and rotationY: 这些属性控制了在2D和3D坐标系中围绕着中心点(锚点)的旋转。旋转
  • scaleX and scaleY:这些属性控制了在2d坐标系中围绕着中心点(锚点)的缩放。缩放
  • pivotX and pivotY: 这些属性控制了中心点的位置,它与旋转和缩放转换有关。默认情况下,中心点位于对象的正中央。锚点
  • x and y: 用来描述view在容器中的最终坐标,是左部和上部加上x和y的偏移量的和。
  • alpha: 代表着view的透明度变化。默认值为1(不透明),越接近0代表着越透明(看不见)。
动画化一个view对象的属性,如它的颜色或旋转值,你只需要做的就是创建一个属性动画师,并且指定你想要动画化的属性。如:
    
ObjectAnimator.ofFloat(myView, "rotation", 0f, 360f);
更多关于如何创建动画师的信息,看上文的 #使用ValueAnimator制作动画#使用ObjectAnimator制作动画

使用ViewPropertyAnimator制作动画

  ViewPropertyAnimator  提供了一个简单的方法来并行动画化几个视图属性,使用一个简单的底层 Animator  对象。它的行为更像是 ObjectAnimator ,因为它修改了view的真实属性值,但是更加高效的是它同时动画化许多属性。另外,关于使用 ViewPropertyAnimator的代码更加简洁和易于阅读。接下来的代码片段展示了复合 ObjectAnimator对象,单一的 ObjectAnimator ,和 ViewPropertyAnimator  在同时动画化x和y属性时的不同。
Multiple ObjectAnimator objects
   
ObjectAnimator animX = ObjectAnimator.ofFloat(myView, "x", 50f);
ObjectAnimator animY = ObjectAnimator.ofFloat(myView, "y", 100f);
AnimatorSet animSetXY = new AnimatorSet();
animSetXY.playTogether(animX, animY);
animSetXY.start();
One ObjectAnimator
   
PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("x", 50f);
PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("y", 100f);
ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvyY).start();
ViewPropertyAnimator
   
myView.animate().x(50f).y(100f);
更多关于 ViewPropertyAnimator ,的详细信息,请看相应的安卓开发博文 blog post .

在XML文件中声明动画

属性动画系统允许你在xml文件中什么属性动画,代替编程实现。在xml 中定义你的动画,可以更加方便的复用你的动画且更加容易的对动画排序。
为了区分动画文件,使用了 那些使用传统视图动画框架的 新的属性动画API,始于安卓3.1,你可以在 res/animator/  目录(不是 res/anim/ )下保持你的属性动画xml文件。使用 animator 目录是可选的,但是如果你想使用ADT插件(ADT 11.0.0+)的视图编辑工具时,这是必须的。因为ADT只会查找在 res/animator/  目录下的属性动画文件。
下面是属性动画类对应的xml标签元素:
following 下面一个案例播放了两套顺序播放的动画对象,第一个对象通过嵌套设置两个动画对象一起播放:
    
<set android:ordering="sequentially">
<set>
<objectAnimator
android:propertyName="x"
android:duration="500"
android:valueTo="400"
android:valueType="intType"/>
<objectAnimator
android:propertyName="y"
android:duration="500"
android:valueTo="300"
android:valueType="intType"/>
</set>
<objectAnimator
android:propertyName="alpha"
android:duration="500"
android:valueTo="1f"/>
</set>
运行这个动画,你必须在你代码的 AnimatorSet对象中展开这个xml资源,然后为在动画开始之前为这里的所有动画设置目标对象。调用 setTarget()  来设置一个简单对象,为方便,目标会应用于所有 AnimatorSet 的子节点。代码如下:
    
AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext,
R.anim.property_animator);
set.setTarget(myObject);
set.start();
更多关于xml语法定义属性动画的信息,请看   Animation Resources .
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值