动画和图形:属性动画

来源:互联网 发布:java 面向切面编程 编辑:程序博客网 时间:2024/06/07 05:27

属性动画系统是一个强大的框架,允许您展示几乎任何动画。 您可以定义一个动画以随时间更改任何对象属性,无论它是否绘制到屏幕。 属性动画在指定的时间长度内更改属性(对象中的字段)值。 要动画某些东西,您可以指定要对其进行动画处理的对象属性,例如对象在屏幕上的位置,要对其进行动画处理的时间以及要在其间进行动画处理的值。


属性动画系统允许您定义动画的以下特征:

1、持续时间:您可以指定动画的持续时间。 默认长度为300 ms。


2、时间插值:您可以指定如何根据动画当前所用时间计算属性值。


3、重复计数和行为:您可以指定是否在持续时间结束时重复动画,并重复播放动画的次数。 您还可以指定是否要相反地播放动画。 将其设置为反向播放动画向前,然后反复向后,直到达到重复次数。


4、动画集:您可以将动画组合到一起或顺序播放或指定延迟之后的逻辑集。


5、帧刷新延迟:您可以指定刷新动画帧的频率。 默认设置为每10 ms更新一次,但是应用程序刷新帧的速度最终取决于系统整体的繁忙程度,以及系统能够为底层定时器提供多长时间的服务。



一、属性动画如何运作

首先,我们来看一个动画如何工作,一个简单的例子。 图1描绘了一个假设的对象,它以x属性为动画,表示其在屏幕上的水平位置。 动画的持续时间设置为40 ms,行驶距离为40像素。 每10 ms,这是默认的帧刷新率,对象水平移动10像素。 在40ms结束时,动画停止,物体在水平位置40处结束。这是具有线性插值的动画的示例,意味着物体以恒定的速度移动。


图1.线性动画示例


您还可以指定具有非线性内插的动画。 图2示出了在动画开始时加速的假想对象,并且在动画结束时减速。 物体仍然在40毫秒内移动40像素,但是非线性。 一开始,这个动画加速到中途,然后从中途减速直到动画结束。 如图2所示,动画开始和结束时行进的距离小于中间。


图2.非线性动画的示例


我们来详细了解属性动画系统的重要组件如何计算如上所示的动画。 图3描绘了主要类之间如何工作。


图3.如何计算动画


ValueAnimator对象跟踪您的动画的时间,例如动画已运行多长时间,以及动画所属属性的当前值。


ValueAnimator封装了TimeInterpolator,它定义了动画插值,还有一个TypeEvaluator,它定义了如何计算动画属性的值。 例如,在图2中,使用的TimeInterpolator将为AccelerateDecelerateInterpolator,TypeEvaluator将为IntEvaluator。


要启动动画,请创建一个ValueAnimator,并为其创建动画的属性以及动画持续时间给出它的开始和结束值。 当你调用start()动画开始。 在整个动画过程中,ValueAnimator根据动画的持续时间和经过多少时间,计算0到1之间的经过分数。 经过的分数表示动画完成的时间百分比,0表示0%,1表示100%。 例如,在图1中,t = 10ms时的经过分数为0.25,因为总持续时间为t = 40ms。


当ValueAnimator完成计算经过的分数时,它调用当前设置的TimeInterpolator,以计算插值分数。 插值分数将经过的分数映射到考虑到设置的时间插值的新分数。 例如,在图2中,由于动画缓慢加速,所以在t = 10 ms时,内插分数约为.15,小于经过分数.25。 在图1中,插值分数总是与经过分数相同。


当计算插值分数时,ValueAnimator将根据插值分数,起始值和动画的结束值,调用相应的TypeEvaluator来计算您要动画化的属性值。 例如,在图2中,在t = 10 ms时插值分数为.15,因此该时间的属性值为.15 X(40 - 0)或6。


API Demos示例项目中的com.example.android.apis.animation包提供了许多关于如何使用属性动画系统的示例。



二、属性动画如何与视图动画不同

视图动画系统提供了只能对View对象进行动画化的功能,因此,如果您想为非View对象设置动画效果,则必须实现自己的代码。 视图动画系统也受到限制,因为它仅将View对象的几个方面暴露给动画,例如视图的缩放和旋转,而不是背景颜色。


视图动画系统的另一个缺点是它只修改了View的绘制位置,而不是实际的View本身。 例如,如果您将动画按钮移动到屏幕上,则按钮正确绘制,但您可以单击按钮的实际位置不会更改,因此您必须实现自己的逻辑来处理此问题。


使用属性动画系统,这些约束被完全删除,您可以对任何对象(视图和非视图)的任何属性进行动画处理,并且对象本身实际上进行了修改。 属性动画系统在执行动画的过程中也更为强大。 在高层次上,您可以将动画师分配给要进行动画化的属性,例如颜色,位置或大小,并可以定义动画的各个方面,如多个动画制作工具的插值和同步。


然而,视图动画系统需要较少的时间来设置,并且需要较少的代码来写入。 如果视图动画完成了您需要执行的所有操作,或者如果现有代码已经按照您想要的方式工作,则不需要使用属性动画系统。 如果出现用例,在不同情况下使用动画系统也可能是有意义的。



三、API概览

您可以在android.animation中找到大部分属性动画系统的API。 因为视图动画系统已经在android.view.animation中定义了许多插值器,所以您也可以在属性动画系统中使用这些插值器。 下表描述了属性动画系统的主要组件。


Animator类提供了创建动画的基本结构。 您通常不直接使用此类,因为它只提供必须扩展的最小功能,以完全支持动画值。 以下子类扩展了Animator:

Table 1. Animators

类描述ValueAnimator属性动画的主要定时引擎,也可以计算要动画的属性的值。它具有计算动画值的所有核心功能,并包含每个动画的时序细节,动画重复的信息,接收更新事件的收听者以及设置自定义类型进行评估的能力。动画属性有两部分:计算动画值,并在动画对象和属性上设置这些值。 ValueAnimator不执行第二部分,因此您必须监听由VueueAnimator计算的值的更新,并使用自己的逻辑修改要进行动画化的对象。 有关详细信息,请参阅有关使用ValueAnimator进行动画化的部分。ObjectAnimatorValueAnimator的子类,允许您将目标对象和对象属性设置为动画。 当该类计算动画的新值时,此类将相应地更新该属性。 你想在大多数时候使用ObjectAnimator,因为它使得在目标对象上动画化值的过程更容易。 但是,有时候您希望直接使用VueueAnimator,因为ObjectAnimator还有一些限制,例如需要在目标对象上存在特定的教程方法。AnimatorSet提供一种将动画分组在一起的机制,以便它们相互运行。 您可以将动画设置为一起播放,顺序播放或指定延迟播放。 有关更多信息,请参阅有关使用动画组合编排多个动画的部分。

评估者告诉属性动画系统如何计算给定属性的值。 它们获取Animator类提供的时间数据,动画的开始和结束值,并根据此数据计算属性的动画值。 属性动画系统提供以下评估者:

Table 2. Evaluators

类/接口描述IntEvaluator用于计算int属性值的默认计算器。FloatEvaluator用于计算float属性值的默认值。ArgbEvaluator用于计算以十六进制值表示的颜色属性的值的默认评估器。TypeEvaluator一个允许您创建自己的评估器的界面。 如果要动画化不是int,float或color的对象属性,则必须实现TypeEvaluator接口以指定如何计算对象属性的动画值。 如果要处理不同于默认行为的类型,还可以为int,float和color值指定自定义的TypeEvaluator。 有关如何编写自定义评估程序的更多信息,请参阅有关使用TypeEvaluator的部分。

时间插值器定义如何计算动画中的特定值作为时间的函数。 例如,您可以指定动画在整个动画中线性发生,这意味着动画在整个时间内均匀移动,或者您可以指定使用非线性时间的动画,例如,在动画开始时加速并在动画结束时减速。 表3描述了android.view.animation中包含的插值器。 如果没有提供的插件适合您的需要,请执行TimeInterpolator界面并创建自己的界面。 有关如何编写自定义插值器的更多信息,请参阅使用插值器。

Table 3. Interpolators

类/接口描述AccelerateDecelerateInterpolator一个插值器,它的变化率开始慢慢地结束,但是通过中间加速。AccelerateInterpolator一个内插器,其变化率慢慢开始,然后加速。AnticipateInterpolator一个内插器,其变化开始向后,然后向前摆动。AnticipateOvershootInterpolator一个内插器,其变化向后开始,向前摆动并超过目标值,然后最终返回到最终值。BounceInterpolator一个内插器,其更改在最后弹跳。CycleInterpolator一个内插器,其动画重复一个指定的周期数。DecelerateInterpolator一个插值器,其变化率迅速开始,然后减速。LinearInterpolator一个变化率不变的插值器。OvershootInterpolator一个内插器,其变化向前偏移并超过最后一个值,然后返回。TimeInterpolator一个允许您实现自己的插件的界面。


四、用ValueAnimator进行动画处理

ValueAnimator类允许您通过指定一组int,float或颜色值来动画化,为动画持续时间对某些类型的值进行动画处理。 通过调用其中一种工厂方法获得ValueAnimator:ofInt(),ofFloat()或orObject()。 例如:

ValueAnimator animation = ValueAnimator.ofFloat(0f, 100f);animation.setDuration(1000);animation.start();

在此代码中,当start()方法运行时,ValueAnimator将开始计算0到100之间动画的值,持续时间为1000 ms。


您还可以通过执行以下操作来指定自定义类型以进行动画处理:

ValueAnimator animation = ValueAnimator.ofObject(new MyTypeEvaluator(), startPropertyValue, endPropertyValue);animation.setDuration(1000);animation.start();

在此代码中,当start()方法运行时,ValueAnimator将使用MyTypeEvaluator提供的逻辑持续1000 ms,在startPropertyValue和endPropertyValue之间开始计算动画值。


您可以通过向ValueAnimator对象添加AnimatorUpdateListener来使用动画值,如以下代码所示:

animation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {    @Override    public void onAnimationUpdate(ValueAnimator updatedAnimation) {        // You can use the animated value in a property that uses the        // same type as the animation. In this case, you can use the        // float value in the translationX property.        float animatedValue = (float)updatedAnimation.getAnimatedValue();        textView.setTranslationX(animatedValue);    }});

在onAnimationUpdate()方法中,您可以访问更新的动画值,并在其中一个视图的属性中使用它。 有关侦听器的更多信息,请参阅有关动态侦听器的部分。



五、用ObjectAnimator进行动画处理

ObjectAnimator是ValueAnimator的一个子类(在前面的部分讨论过),它将ValueAnimator的定时引擎和值计算结合起来,使目标对象的命名属性动画化。 这使得任何对象变得更加简单,因为您不再需要实现ValueAnimator.AnimatorUpdateListener,因为动画属性会自动更新。


实例化一个ObjectAnimator类似于一个ValueAnimator,但是你也可以指定该对象和该对象的属性(作为一个String)的名称以及值之间的动画值:

ObjectAnimator animation = ObjectAnimator.ofFloat(textView, "translationX", 100f);animation.setDuration(1000);animation.start();

要使ObjectAnimator更新属性正确,您必须执行以下操作:

1、您正在动画的对象属性必须以set <PropertyName>()的形式具有setter函数(在骆驼情况下)。 因为ObjectAnimator在动画过程中自动更新属性,所以它必须能够使用此setter方法访问该属性。 例如,如果属性名称为foo,则需要具有setFoo()方法。 如果此setter方法不存在,您有三个选项:

 1)、如果您有权这样做,请将setter方法添加到类中。

 2)、使用您有权更改的包装类,并使该包装器使用有效的setter方法接收该值并将其转发到原始对象。

 3)、改用ValueAnimator。


2、如果在ObjectAnimator工厂方法之一中为values...参数指定了一个值,则假定它是动画的结束值。 因此,您正在动画的对象属性必须具有用于获取动画起始值的getter函数。 getter函数必须以get <PropertyName>()的形式。 例如,如果属性名称为foo,则需要使用getFoo()方法。


3、您要动画化的属性的getter(如果需要)和setter方法必须与您为ObjectAnimator指定的起始值和结束值相同的类型运行。 例如,如果构造以下ObjectAnimator,则必须具有targetObject.setPropName(float)和targetObject.getPropName(float):

ObjectAnimator.ofFloat(targetObject, "propName", 1f)

4、根据您要动画的属性或对象,您可能需要在视图上调用invalidate()方法来强制屏幕使用更新的动画值重新绘制。 您可以在onAnimationUpdate()回调中执行此操作。 例如,当Drawable对象重新绘制时,可以对Drawable对象的color属性进行动画化,只会导致屏幕更新。 View上的所有属性设置,如setAlpha()和setTranslationX()都会使视图正确无效,因此在使用新值调用这些方法时,不需要使视图无效。 有关侦听器的更多信息,请参阅有关动态侦听器的部分。



六、用动画组合编排多个动画

在许多情况下,您想要播放依赖于另一个动画启动或完成的动画。 Android系统允许您将动画组合到AnimatorSet中,以便您可以指定是否同时,顺序启动或在指定的延迟之后启动动画。 您也可以将AnimatorSet对象嵌套在彼此中。


从弹跳球实例(为了简化而修改)获取的以下示例代码以以下方式播放以下Animator对象:

1、播放bounceAnim.

2、同时播放squashAnim1,squashAnim2,stretchAnim1和stretchAnim2。

3、播放bounceBackAnim.

4、播放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();

有关如何使用动画组合的更完整的示例,请参阅APIDemos中的Bouncing Balls示例。



七、动画监听器

您可以在动画持续时间内监听下面介绍的监听器的重要事件。

1、Animator.AnimatorListener

 1)、onAnimationStart() - 动画启动时调用。

 2)、onAnimationEnd() - 动画结束时调用。

 3)、onAnimationRepeat() - 当动画重复时被调用。

 4)、onAnimationCancel() - 动画取消时调用。 取消的动画也会调用OnAnimationEnd(),无论它们如何结束。


2、ValueAnimator.AnimatorUpdateListener

 1)、onAnimationUpdate() - 呼吁动画的每一帧。 监听此事件以使用ValueAnimator在动画期间生成的计算值。 要使用该值,请查询传递给事件的ValueAnimator对象以getAnimatedValue()方法获取当前动画值。 如果您使用ValueAnimator,则需要实现此侦听器。

 根据您要动画的属性或对象,您可能需要在视图上调用invalidate(),以强制屏幕区域使用新的动画值重新绘制。 例如,当Drawable对象重新绘制时,动画化Drawable对象的颜色属性只会导致更新屏幕。 View上的所有属性设置,如setAlpha()和setTranslationX()都会使视图正确无效,因此在使用新值调用这些方法时,不需要使视图无效。


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


例如,API演示中的Bouncing Balls示例仅为onAnimationEnd()回调创建AnimatorListenerAdapter:

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


八、动画视图组的布局更改

属性动画系统提供了对ViewGroup对象进行动画更改的功能,并提供了一种简单的方法来自动生成View对象。


您可以使用LayoutTransition类在ViewGroup中对动画布局进行更改。 ViewGroup中的视图可以在您添加到ViewGroup或将其从ViewGroup中删除时或当您使用VISIBLE,INVISIBLE或GONE调用View的setVisibility()方法时,看到并消失的动画。 当您添加或删除视图时,ViewGroup中的剩余视图也可以动画进入新的位置。 您可以通过调用setAnimator()并传递具有以下LayoutTransition常量之一的Animator对象来在LayoutTransition对象中定义以下动画:

1、APPEARING - 指示在容器中出现的项目上运行的动画的标志。

2、CHANGE_APPEARING -指示由于容器中出现新项目而改变的项目上运行的动画的标志。

3、DISAPPEARING - 指示在从容器中消失的物品上运行的动画的标志。

4、CHANGE_DISAPPEARING - 指示由于项目从容器中消失而改变的项目上运行的动画的标志。


您可以为这四种类型的事件定义自己的自定义动画,以自定义布局过渡的外观,或者只是告诉动画系统使用默认动画。


API Demos中的LayoutAnimations示例显示了如何为布局转换定义动画,然后在要动画化的View对象上设置动画。


LayoutAnimationsByDefault及其相应的layout_animations_by_default.xml布局资源文件显示如何启用XML中ViewGroups的默认布局转换。 您唯一需要做的是为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" />

将此属性设置为true自动动画从ViewGroup添加或删除的视图以及ViewGroup中的其余视图。



九、使用TypeEvaluator

如果要为Android系统未知的类型设置动画,您可以通过实现TypeEvaluator界面来创建自己的评估者。 Android系统已知的类型为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(或ObjectAnimator)运行时,它会计算动画的当前经过分数(0到1之间的值),然后根据您使用的内插器计算插值版本。 插值分数是您的TypeEvaluator通过分数参数获得的分数,因此您不必在计算动画值时考虑内插器。



十、使用Interpolators

内插器定义如何根据时间函数计算动画中的特定值。 例如,您可以指定动画在整个动画中线性发生,这意味着动画在整个时间内均匀移动,或者您可以指定使用非线性时间的动画,例如,在动画开始或结束时使用加速或减速。


动画系统中的插件从Animators接收代表动画经过时间的一小部分。 内部人员修改此部分,以符合其旨在提供的动画类型。 Android系统在android.view.animation包中提供了一组常见的插件。 如果这些都不符合您的需求,您可以实现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 elapsedElapsed fraction/Interpolated fraction (Linear)Interpolated fraction (Accelerate/Decelerate)000200.2.1400.4.345600.6.8800.8.9100011

如表所示,LinearInterpolator以每200ms通过的速度以相同的速度更改值.2。 AccelerateDecelerateInterpolator将线速度更改速度快于LinearInterpolator在200ms和600ms之间,而在600ms和1000ms之间更慢。



十一、指定关键帧

关键帧对象由时间/值对组成,可以让您在动画的特定时间定义特定状态。 每个关键帧还可以具有自己的插值器,以在之前关键帧的时间与该关键帧的时间之间的时间间隔内控制动画的行为


要实例化一个关键帧对象,您必须使用其中一个工厂方法,即Int(),ofFloat()或orObject()来获取适当类型的关键帧。 然后调用Keyframe()工厂方法来获取一个PropertyValuesHolder对象。 拥有该对象后,您可以通过将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);

有关如何使用关键帧的更完整的示例,请参阅APIDemos中的MultiPropertyAnimation示例。




十二、动画视图

属性动画系统允许View对象的流线型动画,并且比视图动画系统提供了一些优点。 视图动画系统通过更改绘制方式来变换View对象。 这是在每个视图的容器中处理的,因为View本身没有要处理的属性。 这导致View被动画化,但是在View对象本身没有改变。 这导致诸如对象仍然存在于其原始位置的行为,即使它被绘制在屏幕上的不同位置。 在Android 3.0中,添加了新的属性和相应的getter和setter方法来消除这个缺点。


通过更改View对象中的实际属性,属性动画系统可以在屏幕上生成视图。 此外,Views还会自动调用invalidate()方法来刷新屏幕,每当其属性更改时。 View类中的新属性可以促进属性动画的有:

1、translationX和translationY:这些属性控制视图所在的位置,其左侧和顶部坐标是由其布局容器设置的三角形。

2、旋转,旋转X和旋转Y:这些属性控制旋转点在2D(旋转属性)和3D周围旋转。

3、scaleX和scaleY:这些属性控制视图围绕其枢轴点的2D缩放。

4、pivotX和pivotY:这些属性控制旋转点的位置,旋转和缩放变换发生在该位置。 默认情况下,枢轴点位于对象的中心。

5、x和y:这些是简单的实用程序属性,用于在其容器中描述View的最终位置,作为左和顶值和translationX和translationY值的总和。

6、alpha:表示视图上的Alpha透明度。 该值默认为1(不透明),值为0表示完全透明(不可见)。


要为View对象的属性(如其颜色或旋转值)生成动画,您需要做的只是创建一个属性动画,并指定要设置动画的View属性。 例如:


ObjectAnimator.ofFloat(myView, "rotation", 0f, 360f);

有关创建动画师的更多信息,请参阅使用ValueAnimator和ObjectAnimator进行动画化的部分。


一)、使用ViewPropertyAnimator进行动画处理

ViewPropertyAnimator提供了一种简单的方式来使用单个底层的Animator对象并行地对视图的多个属性进行动画化。 它的行为非常类似于ObjectAnimator,因为它会修改视图属性的实际值,但在一次动画化多个属性时效率更高。 此外,使用ViewPropertyAnimator的代码更加简洁易读。 以下代码片段显示了在同时动画化视图的x和y属性时使用多个ObjectAnimator对象,单个ObjectAnimator和ViewPropertyAnimator的差异。


多个ObjectAnimator对象

ObjectAnimator animX = ObjectAnimator.ofFloat(myView, "x", 50f);ObjectAnimator animY = ObjectAnimator.ofFloat(myView, "y", 100f);AnimatorSet animSetXY = new AnimatorSet();animSetXY.playTogether(animX, animY);animSetXY.start();

一个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的更多详细信息,请参阅相应的Android Developers博客文章。



十三、声明XML中的动画

属性动画系统允许您使用XML声明属性动画,而不是以编程方式执行。 通过在XML中定义动画,您可以轻松地在多个活动中重新使用动画,并更轻松地编辑动画序列。


要区分使用新的属性动画API的动画文件与使用旧版视图动画框架的动画文件,从Android 3.1开始,您应将属性动画的XML文件保存在res / animator /目录中。


以下属性动画类使用以下XML标签支持XML声明:

  • ValueAnimator - <animator>
  • ObjectAnimator - <objectAnimator>
  • AnimatorSet - <set>

要查找您可以在XML声明中使用的属性,请参阅动画资源。 以下示例顺序播放两组对象动画,第一个嵌套集合将两个对象动画一起播放:
<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>

为了运行此动画,您必须将代码中的XML资源充足到AnimatorSet对象,然后在启动动画集之前设置所有动画的目标对象。 调用setTarget()为AnimatorSet的所有子项设置单个目标对象。 以下代码显示如何执行此操作:
AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext,    R.anim.property_animator);set.setTarget(myObject);set.start();

您还可以使用XML声明ValueAnimator,如以下示例所示:
<animator xmlns:android="http://schemas.android.com/apk/res/android"    android:duration="1000"    android:valueType="floatType"    android:valueFrom="0f"    android:valueTo="-100f" />

要在代码中使用以前的ValueAnimator,您必须对对象进行inflate,添加AnimatorUpdateListener,获取更新的动画值,并将其用于其中一个视图的属性,如以下代码所示:
ValueAnimator xmlAnimator = (ValueAnimator) AnimatorInflater.loadAnimator(this,        R.animator.animator);xmlAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {    @Override    public void onAnimationUpdate(ValueAnimator updatedAnimation) {        float animatedValue = (float)updatedAnimation.getAnimatedValue();        textView.setTranslationX(animatedValue);    }});xmlAnimator.start();

有关定义属性动画的XML语法的信息,请参阅动画资源。


十四、对UI性能的影响
更新UI的动画师会为动画运行的每个帧引起额外的渲染工作。 因此,使用资源密集型动画可能会对您的应用程序的性能产生负面影响。

为UI创建动画所需的工作被添加到渲染管道的动画阶段。 您可以通过启用Profile GPU渲染和监视动画阶段来确定您的动画是否影响了您的应用程序的性能。 有关更多信息,请参阅配置文件GPU渲染演练。

原创粉丝点击