StupidBeauty
Read times:2661Posted at: - no title specified

安卓开发指南翻译:属性动画,Property Animation

内容目录

属性动画的工作方式

属性动画与视图动画有何不同

应用编程接口概述

使用ValueAnimator来进行动画

使用ObjectAnimator来进行动画

使用AnimatorSet将多个动画组合起来

动画监听器

对ViewGroups的布局变更进行动画

使用TypeEvaluator

使用插值器

指定关键帧

对视图(Views)进行动画

使用ViewPropertyAnimator进行动画

在XML中声明动画

属性动画系统,是一个稳健的框架,使得妳能够对几乎任何东西应用动画。妳可以定义一个动画,用来让任何对象的属性随着时间改变,而无论该对象是否被绘制到屏幕上了。属性动画,能够在指定的时间段内改变某个属性(某个对象中的某个字段)的值。为了以动画展现某个东西,妳需要指定:想要让其以动画形式展现的对象属性,例如某个对象在屏幕上的位置;妳希望动画持续多长时间;以及,动画的起始值和终止值是什么。

属性动画系统,使得妳能够定义某个动画的以下特性:

  • •.持续时间:可指定动画的持续时间。默认长度是300毫秒

  • •.时间插值方式:可以指定,属性的值与动画的逝去时间之间是什么样的函数关系。

  • •.重复次数及行为:妳可以指定,当某个动画到达其一遍的结尾的时候,是否要重复,以及,重复多少次。还可以指定,是否希望该动画反向播放。将它设置为反向播放的话,则,在重复的过程中会以正向和反向交替进行,直到达到重复次数为止。

  • •.动画集合:妳可以将多个动画组合成逻辑集合,让它们一起运行,或者依次运行,或者在经过特定延迟之后运行。

  • •. 帧刷新延迟:妳可以指定,以什么频率来刷新妳的动画中的帧。默认值是每隔10毫秒刷新一次,但是,妳的应用程序能够刷新帧的速度,最终是由以下两点决定的:系统整体上有多少繁忙;以及,系 统可以以多快的速度为底层时钟提供服务。

属性动画的工作方式

首先 ,让我们以一个简单的示例来研究动画 的工作方式。 1展示 的是, 一个假想的对象,它的 x 属性(代表 着它在屏幕上的水平位置 )参与了动画过程。动画 的持续时间设置为 40毫秒,移动距离 40像素 。按照默认 的帧刷新率,每隔 10毫秒, 该对象会在水平方向上移动 10像素 40毫秒 的终止时刻,动画停止 而该对象, 也会停止在水平方向上 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 = 10毫秒时刻的逝去比例值是.25,因为 ,整个持续时间是 t = 40毫秒

ValueAnimator 计算出了逝去比例值之后, 会调用当前设置的 TimeInterpolator ,由该对象来计算出一个 插值比例 。插值比例 值,即为, 将逝去比例值映射到一个新的比例值上,在映射过程中会将 已设置的 插值函数计算在内。例如 在图 2 中,因为 该动画是缓慢启动的,所以 在t = 10 毫秒时刻,插值比例 值,约为.15,是小于逝去比例值.25 而在图 1 中,插值比例 值是永远与逝去比例值相等的。

计算 出了插值比例值之后, ValueAnimator 会调用适当的 TypeEvaluator 以计算出当前正在进行动画 的那个属性的值,计算过程 中是以以下数据作为依据的:插值比例 值;动画 起始 值;动画的终止值。例如, 在图 2 中,在 t = 10毫秒时刻,插值比例值是.15 ,因此, 在那个时刻,属性 的值是.15 X (40 - 0) 也就是 6。

应用编程接口演示 示例项目 中的 com.example.android.apis.animation 包,提供了狠多关于如何使用属性动画系统的示例。

属性动画与视图动画有何不同

视图动画系统 提供了对 View 对象进行动画的功能,因此,如果 妳想对非 View 对象进行动画,则,需要自己实现相应的代码。 同时, 视图动画系统 ,还有着它自身的限制, 它只暴露 出了 View 对象的少数属性 以用于动画,例如 缩放 、旋转, 而像背景颜色这样的属性,却未提供动画支持。

视图动画系统的另一个缺点就是,它只是修改了该View 被绘制的位置,而未曾修改该View 本身。例如,假设妳对某个按钮启动动画效果,让它从屏幕上飞过,那么,该按钮会正确地绘制出这样的效果,但是,实际可供妳点击该按钮的那个位置,却未曾改变,因此,妳需要自行实现代码来处理这个情况。

使用属性动画系统的时候,这些限制都被解除了,妳可以对任意对象(View和非View)的任意属性进行动画,并且该对象本身是切实被改变了。属性动画系统,在驱动动画的过程中也更加稳健。在一个较高的级别上,妳向妳希望展现出动画的那些属性(例如颜色、位置或尺寸)赋予动画器(animators),并且定义该动画的相关属性,例如插值以及多个动画器之间的同步关系。

然而,另一方面,视图动画系统,设置起来更快,所需编写的代码更少。如果视图动画已经能够完全支持妳所需要实现的功能,或者,妳的已有代码已经狠好地工作着了,那么,妳就不需要使用属性动画系统了。另外,根据实际情况来判断,可能会需要同时使用这两种动画系统。

应用编程接口概述

妳可以在 android.animation 中找到属性动画系统的大部分应用编程接口。由于视图动画系统已经 android.view.animation 中定义了狠多插值器,所以 ,妳也可以在属性动画系统中使用这些插值器。 下表说明了属性动画系统的主要组件。

Animator 类,提供了用于创建动画的基本结构。 一般情况下,妳并不直接使用这个类,因为, 它只提供了最小 的功能,必须 经过扩展才能完全地支持对值进行动画。以下 类,扩展了 Animator

1.  动画

说明

ValueAnimator

属性动画系统中的主要时序引擎,它也会为对之进行动画的属性计算其值。它具有用来计算动画值的所有核心功能,以及:每个动画的时序细节;关于某个动画是否重复的信息;接收更新事件的监听器;以及,设置那些要计算其值的自定义定义的能力。在对属性进行动画的过程中有两件事:计算出动画值;以及,将对应的值设置给要对其进行动画的那个对象的对应属性。 ValueAnimator 并不处理第二点,因此,妳必须监听 ValueAnimator 计算出来的那些值的变化,并且,使用妳自己的逻辑来对那些要进行动画的对象设置其值。参考 利用 ValueAnimator 来实现动画 小节,以了解更多细节。

ObjectAnimator

ValueAnimator 的一个子类,使得妳能够设置要对其进行动画的目标对象及对象属性。这个类,在为动画过程计算出一个新的值的时候,会对应地更新目标属性的值。大部分情况下,妳应当使用 ObjectAnimator ,因为,它使得对目标对象的值的动画过程变得容易得多。然而,某些情况下,妳需要直接使用 ValueAnimator ,因为, ObjectAnimator 具有某些限制,例如,要求在目标对象中存在特定的访问方法。

AnimatorSet

提供一种将多个动画组合起来的机制,使得它们之间能够按照一定的关系来运行。妳可以将多个动画设置为一起运行、串行运行或者经过特定的延迟之后运行。参考 利用动画 器分组来对多个动画进行计划 小节以了解更多信息。

算值器(Evaluators),告知属性动画系统要如何计算指定属性 的值。它们需要获取 到由某个 Animator 类提供的时序数据、该动画的起始及终止值,然后,根据 这些数据来计算出该属性的动画值。属性动画系统提供 了以下算值器:

2. 算值器

类/接口

说明

IntEvaluator

默认的用来针对 int 属性计算其值的算值器。

FloatEvaluator

默认的用来针对 float 属性计算其值的算值器。

ArgbEvaluator

用来针对以十六进制形式表示的颜色属性计算其值的默认算值器。

TypeEvaluat or

这个接口,允许妳创建自己的算值器。如果妳要对其进行动画的那个对象属性 并不是 int float 或颜色,那么,妳必须实现 TypeEvaluator 接口,以指定,如何计算该对象属性的动画值。另外,对于 int float 和颜色值,如果妳想按照与默认行为所不同的方式来处理那些类型的话,妳同样可以为它们指定一个自定义的 TypeEvaluator 。参考 使用 一个 TypeEvaluator 小节,以了解,如何编写一个自定义的算值器。

时序插值 器,定义的是,动画过程 中的某个值,要以怎么样的一个关于时间的函数来计算。例如 妳可以指定让动画 在整个过程中以线性方式来进行,也就是说,动画 在整个过程中都是匀速发展的 。或者 也可以指定让动画以非线性的时间来进行,例如 在开头阶段加速 在结束阶段减速。 3列出 android.view.animation 中包含的那些插值器。如果 这些插值器都不能满足妳的需求,那么,请实现 TimeInterpolator 接口,以创建妳自己的插值器。参考 使用插值 以了解更多关于编写自定义插值器的信息。

3.  插值

类/接口

说明

AccelerateDecelerateInterpolator

这个插值器,在开始阶段和结束阶段的速率缓慢变化,而在中间阶段加速。

Acce lerateInterpolator

这个插值器,开始阶段的速率缓慢变化,之后加速。

AnticipateInterpolator

这个插值器,它先向后变化,然后快速向前。

AnticipateOv ershootInterpolator

这个插值器,它先向事变化,然后快速向前,然后超出目标值,然后回到最终值。

BounceInterpolator

这个插值器,会在结束阶段产生弹跳效果。

CycleInterpolat or

这个插值器,其动画效果会重复运行指定次数。

DecelerateInterpolator

这个插值器,其速率在开始阶段狠快,然后减速。

LinearInterpolator

这个插值器,其速率恒定。

OvershootI nterpolator

这个插值器,首先快速向前,并且越过目标值,然后回到目标值。

TimeInterpolator

这个接口,允许妳实现自己的插值器。

使用ValueAnimator来进行动画

ValueAnimator 类,使得 在动画的持续时间里对某种类型的值进行动画,具体做法就是指定一组要进行动画的 int float 或颜色 值。 妳通过调用某个工厂方法来获取一个 ValueAnimator ofInt() ofFloat() ofObject() 。例如:

ValueAnimator animation = ValueAnimator . ofFloat ( 0f , 1f );

animation . setDuration ( 1000 );

animation . start ();

在这砣代码中,当 start() 方法开始执行的时候,该 ValueAnimator 就会开始计算 该动画的值: 其值范围是0到1,持续时间是1000 毫秒。

妳也可以通过以下代码来指定对一个自定义类型进行动画:

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

animation . setDuration ( 1000 );

animation . start ();

在这砣代码中,当 start() 方法开始执行的时候, ValueAnimator 就会开始计算动画的值: 其值范围是 startPropertyValue endPropertyValue ,持续时间是1000 毫秒,并且使用 MyTypeEvaluator 的逻辑来计算。

然而 前面 这两砣代码,都不会对任何对象产生任何效果,因为 ValueAnimator 并不直接操作对象及属性。 妳最想做的事情就是,利用 这些计算出来的值来修改 要对之进行动画的对象。具体做法 就是,定义出将要置于 ValueAnimator 之中的监听器, 以正确地处理该动画的生命周期中的重要事件,例如动画帧的更新。 在实现监听器的过程中, 可以通过调用 getAnimatedValue() 来获取到那次特定 的动画帧更新事件中的计算值。欲知更多关于监听 器的信息,则参考 动画监听 小节。

使用ObjectAnimator来进行动画

ObjectAnimator ValueAnimator 的一个子类(前面已经说过 ), 它将以下功能结合起来了:时序引擎 ValueAnimator 的值计算功能;以及, 对目标对象的某个命名属性进行动画的能力。 这样,对任何对象进行动画的工作就变得容易得多了,因为 ,妳不需要实现 ValueAnimator.AnimatorUpdateListener 了,那些 被动画的属性会自动更新。

ObjectAnimator 的实例化与 ValueAnimator 类似,但是, 除了动画的值范围之外,妳还需要提供动画 的目标对象及它的某个属性的名字(以String 的形式提供):

ObjectAnimator anim = ObjectAnimator . ofFloat ( foo , "alpha" , 0f , 1f );

anim . setDuration ( 1000 );

anim . start ();

为了让 ObjectAnimator 能够正确的更新属性,妳必须做到以下事情:

  • •. 妳要对其进行动画的那个对象属性,必须拥有一个设值函数 ( 以骆驼风格命名 ) ,其形式为 set<propertyName>() 。因为 ObjectAnimator 会在动画过程中自动地更新目标属性 ,所以, 它必须能够使用该设值方法来访问到目标属性。例如 ,如果 该属性的名字是 foo ,那么,妳需要实现一个 setFoo() 方法。如果 该设值方法不存在,那么,妳有三种选择:

    • •.如果妳拥有相应的权限,那么,向那个类中加入这样一个设值方法。

    • •.使用某个妳有权限更改的包装类,让那些包装类以一个有效的设值方法来接收属性值,并且将该属性值转发给原始对象。

    • •. 使用 ValueAnimator

  • •. 如果 妳在 ObjectAnimator 的工厂方法中 只针对 values... 参数指定了一个值,那么,系统 就会假设 妳所设置的是该动画的结束值。 这样的话, 妳要对其进行动画的那个对象属性,必须拥有 一个取值函数,用来获取动画的起始值。取值函数 的形式必须是 get<propertyName>() 。例如,属性名字 foo ,则,需要有一个 getFoo() 方法。

  • •. 妳在对其进行动画的那个属性的 取值 (如果需要的话)和设值方法, 其对应的数据类型,必须与妳向 ObjectAnimator 指定的起始值和终止值的类型相同。例如 ,假设 妳按照以下的代码来构造 ObjectAnimator ,那么, 就必须拥有 targetObject.setPropName(float) targetObject.getPropName(float) 方法:

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

  • •. 取决 于妳在对什么属性或对象进行动画, 妳可能需要 对某个View 调用其 invalidate() 方法,以强迫屏幕按照更新后的动画值来重绘。 妳可以在 onAnimationUpdate() 回调方法中做这件事。例如, 当妳 对某个Drawable 对象进行动画时, 只有在那个对象重绘自身的情况下, 才会引 屏幕画面更新。View 的所有属性设置方法,例如 setAlpha() setTranslationX() ,都会正确地将该View 标记为无效,因此 ,当妳使用这些方法来设置新的值的时候,无需显式地将该View 标记为无效。欲知更多关于监听 器的信息,则参考关于 动画监听 的小节。

使用AnimatorSet将多个动画组合起来

在狠多情况下, 妳都需要让一个动画在另一个动画结束之后才开始。安卓系统允许 妳将多个动画捆绑成为一个 AnimatorSet ,这样,妳就可以指定,多个动画 是要并行启动、串行化启动还是要在延迟一段时间之后启动。 妳还可以将多个 AnimatorSet 对象嵌套起来。

以下示例代码,取自 跳跳球球 示例( 经过了简化 ),会按照下列规则来播放以下 Animator 对象:

  1. 1. 播放 bounceAnim

  2. 2. 同时 播放 squashAnim1 squashAnim2 stretchAnim1 stretchAnim2

  3. 3. 播放 bounceBackAnim

  4. 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 中的 跳跳球球 示例。

动画监听

妳可以使用下列监听器来监听动画持续过程中的那些重要事件。

如果 妳并不想实现 Animator.AnimatorListener 接口中的所有方法,那么,妳可以扩展 AnimatorListenerAdapter 类,而不是实现 Animator.AnimatorListener 接口。 AnimatorListenerAdapter 类提供了那些方法的空白实现, 而妳可以按照需要来覆盖

例如,应用编程接口演示 中的 跳跳球球 示例,创建了一个 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的布局变更进行动画

属性动画系统,除了提供了一种轻易地对 View 对象进行动画的手段之外,还提供了对于ViewGroup 对象的变更情况进行动画的能力。

妳可以使用 LayoutTransition 类来 对ViewGroup 中的布局变更进行动画。ViewGroup 中的那些Views,可以在以下情况下呈现出一个出现动画 或消失动画: 向ViewGroup 中添加它们,或者从 ViewGroup 中删除它们; 妳使用 VISIBLE 、android.view.View#INVISIBLE 或 GONE 参数来调用某个View 的 setVisibility() 方法。 当妳添加或删除Views 的时候,该ViewGroup 中的其它Views 也可以以动画形式移动到各自的新位置。 妳可以 在某个 LayoutTransition 对象中定义以下动画,具体做法 就是,调用 setAnimator() ,并且传入一个 Animator 对象,以及以下的某个 LayoutTransition 常量:

  • •. APPEARING  - 这个标志位,表明, 这个动画针对的是那些正在某个容器中出现的条目。

  • •. CHANGE_APPEARING  - 这个标志位,表明,这个动画针对的是那些因容器 某个新条目的出现而 发生改变的条目。

  • •. DISAPPEARING  - 这个标志位,表明, 这个动画针对的是那些正从某个容器中消失的条目。

  • •. CHANGE_DISAPPEARING  - 这个标志位,表明,这个动画针对的是那些因容器中某个条目的消失而发 生改变的条目。

妳可以定义针对这四种事件的自定义动画,以对妳的布局转场效果进行自定义。或者,直接告诉动画系统要使用默认动画。

应用编程接口演示 中的 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 中那些被添加或删除的Views 以及ViewGroup 中的其它Views 展现动画效果。

使用TypeEvaluator

如果 妳想针对安卓系统所不理解的数据类型进行动画,那么, 妳可以通 实现 TypeEvaluator 接口来创建自己的算值器。安卓系统能够理解 的数据类型包括 int float 和颜色值,分别 IntEvaluator FloatEvaluator ArgbEvaluator 3个类型算值器来提供支持。

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 中,从 fraction 参数接收到的,就是这个插值后的版本,因此 在计算动画值时,妳无需再将插值计算在内了。

使用插值

插值器,定义的是,使用什么样的一个关于时间的函数来计算出动画中的特定值。例如,妳可以指定,让动画在整个过程中线性发展,也就是说,整个过程中,动画都是匀速呈现的。或者,也可以指定,动 画使用非线性时间来发展,例如,在动画的开始或结尾阶段使用加速或减速。

动画系统 中的 插值 器,从Animators 处接收一个百分比,表示的是,动画的逝去时间。然后 插值 器修改这个百分比,以符合 它所提供的动画类型的要求。安卓系统 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 ;

}

下表中,对于一个持续1000毫秒的动画,显示出了两个插值器计算出的近似值:

逝去的毫秒数

逝去百分/插值百分(线性)

插值百分(加速/减速)

0

0

0

200

.2

.1

400

.4

.345

600

.6

.8

800

.8

.9

1000

1

1

从表中可以看到, LinearInterpolator 会以恒定的速度来改变值,每隔200毫秒便改变.2。 AccelerateDecelerateInterpolator 呢,跟 LinearInterpolator 相比, 在200毫秒到600毫秒的时间段里,会让值变化得快一些,而在600毫秒到1000毫秒的时间段之内,会让值变化得慢一些。

指定关键

Keyframe 对象 ,由一个键/值对组成, 可让妳定义出在动画 的特定时间具有的一个特定状态。每个关键 帧, 还可以拥有它自己的插值器,用来控制, 在前一个关键帧到这个关键帧之间的时间段里,动画的行为。

要想实例化一个 Keyframe 对象, 妳必须使用 ofInt() ofFloat() ofObject() 中的某个工厂方法来获取一个适当类型 Keyframe 。然后 ,调用 ofKeyframe() 工厂方法来获取一个 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 示例。

对视图(Views)进行动画

属性动画系统使得妳能够以流水线的方式为View 对象创建动画,并且,相对于视图动画系统,还提供了若干优势。视图动画系统,通过改变各个对象的绘制方式来产生出变换效果。这个过程是由各个View 的容器来完成的,因为,View 本身并不有相应的可操作的属性。其结果就是,View会呈现出动画效果,然而,该View 对象本身并无变化。由此会产生一些奇特的行为,例如,即使某个对象被绘制到了屏幕上狠远的位置,它实际上仍然处于自己原来所在的位置。从安卓3.0开始,引入了新的属性及对应的取值、设值方法,于是就去掉了这个缺陷。

属性动画系统 ,通过改变View 对象 的实际属性来 让Views 在屏幕上呈现动画效果。另外 Views ,在其属性被改变时,也会自动调用 invalidate() 方法来更新屏幕。 View 类中,用来支持属性动画的那些新属性 如下所示:

  • •. translationX translationY 这些属性,控制的是, 该View 相对于其左侧坐标和顶部坐标的偏移值, 后两者是由其布局容器设置的。

  • •. rotation rotationX rotationY 这些属性,控制的是, 以支点为基础, 该对象所具有的二维旋转角度( rotation 属性)和三维旋转角度。

  • •. scaleX scaleY 这些属性,控制的是, 以其支点为中心, 该View 的二维缩放比例。

  • •. pivotX pivotY 这些属性,控制的是,支点 的位置,旋转 和缩放变换就是以支点为中心的。默认情况 下,支点位于该对象的中心。

  • •. x y 这些属性,起到辅助 的作用,描述的是 该View 在其容器中的最终位置值 。分别等价 于,左侧坐标 值和顶部坐标值加上translationX 和translationY 值之后的结果。

  • •. alpha :代表着该View 的透明度。默认 值是 1(完全 不透明 ) ,如果 值为 0 则代表完全透明 ( 不可见 )

要想对某个View 对象的属性进行动画,例如它的颜色或旋转值,妳所需要做的事情就是,创建一个属性动画器,并且指定妳要对其进行动画的View 属性。例如:

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

欲知更多关于创建动画 器的信息,则参考使用 ValueAnimator ObjectAnimator 进行动画的小节。

使用ViewPropertyAnimator进行动画

ViewPropertyAnimator 提供 了一种简单的方式,可利用单个底层的 Animator 对象来同时 对某个 View 的多个属性进行动画。 它的行为与 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 的信息,则参考对应 的安卓开发者 勃客文章

在XML中声明动画

属性动画系统,允许妳利用XML 来声明属性动画,而不是使用代码来声明。通过在XML 中定义动画,妳可以轻易地将动画在多个活动中复用,并且,更轻易地编辑动画序列。

为了将那些使用新的属性动画应用编程接口的动画文件与使用旧式 视图动画 框架的动画文件区分开来, 从安卓 3.1开始 妳应当将那些针对属性动画的 XML文件保存 res/animator/ 目录( 而不是 res/anim/ ) 中。使用 animator 这个目录名,是可选的,但是 ,如果 妳想要在Eclipse ADT 插件(ADT 11.0.0+)中使用布局编辑器的话,则是必需的,因为 ADT 只会在 res/animator/ 目录中搜索属性动画资源。

以下属性动画类支持通过XML 来声明,并且,我们还给出了对应的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 语法的信息,则阅读 动画资源

未知美人

流水不腐

Your opinions
Your name:Email:Website url:Opinion content:
- no title specified

HxLauncher: Launch Android applications by voice commands