API指南 -- 动画和图像(2)-- 属性动画(Property Animation)

来源:互联网 发布:ubuntu 32位下载地址 编辑:程序博客网 时间:2024/06/15 00:21

属性动画系统是一个非常健壮的框架以至于你可以为任何对象设置动画。无论一个对象是否渲染到屏幕,你都可以定义一个动画通过时间变化来改变它的属性。一个属性动画根据指定的时间长度来改变一个属性值(一个对象的域)。为了设置动画,你需要指定动画施加的对象属性,比如对象在屏幕上的位置,还要指定动画时间长度,和动画的区间长度。

 

属性动画系统允许你定义动画的下述几个特征:

时长:你可以指定动画的时长。默认值是300ms。

时间插值:你可以指定一个关于“动画当前过去的时间”的函数来计算当前的属性值。

反复次数和行为:当动画时间到时,你可以指定是否需要重复播放以及重复播放的次数。你也可以指定是否需要反向播放。反向播放意思是从头到尾再从尾到头来回播放,直至达到重复次数。

Animator组合:你可以把几个动画放到一个逻辑组合里,来设定它们同时播放或者顺序播放或者经过指定延迟再播放等。

帧刷新频率:你可以指定多长时间刷新动画的一帧。默认是每10ms刷新一次,但是你的应用刷帧的最终频率取决系统的整体繁忙程度以及系统对底层的计时器的服务响应速度。

 

属性动画如何工作

 

首先,让我们通过一个简单的例子大致看一看动画是如何工作的。图1描述了一个假设的对象在X属性上的动画,这个属性代表了对象在屏幕上的水平位置。动画时长被设置成40ms,动画区间长度为40像素。每10ms,即默认的帧刷新率,对象水平移动10像素。在第40ms时,动画停止,对象停留在水平40像素的位置。这是一个使用线性插值的动画,即对象做匀速运动。


图1 线性动画示例

 

你也可以使用非线性插值的动画。图2描述了一个假设的对象在动画开始时加速,动画结束时减速的情景。这个对象仍然是40ms内移动了40像素,但是是非线性的速度。在开始时,动画一直加速到全程的一半,然后开始减速直到动画的结束。如图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,因为整个时长为t=40ms。

 

当ValueAnimator计算时间分值完成后,它会调用当前设置的TimeInterpolator来计算插分值。一个插分值的计算是根据当前设置的时间插值函数将“时间分值”映射成一个新的分数值。例如,图2,在t=10ms时,插分值大概是0.15,因为动画是慢慢加速的,所以比“时间分值”0.25小。因此此时属性值应为0.15*(40-0),或6。

 

API Demos项目工程里的包 com.example.android.apis.animation 有很多如何使用属性动画的例子。

 

属性动画与组件动画有何不同

 

组件动画系统只工作于View对象,所以如果你想在非View对象上使用动画,你只能自己用代码实现。组件动画系统有个限制,那就是只能作用于View对象上的某些方面,比如View的缩放和旋转,但是不能更改背景色。

 

使用组件动画的另一个不好的地方是它只能修改View的描画位置,而非View本身。比如,你使一个按钮在屏幕中移动,按钮可以被正确地描画,但是按钮的实际位置并没有发生变化,所以你必须实现自己的逻辑控制。

 

使用属性动画,上述所有限制都不存在,你可以使动画作用于任何对象(View或非View对象)的任何属性,而且这个对象本身也确实被修改了。属性动画实现动画的方式也是非常健壮的。在上层,你可以传递给Animator动画施加的对象属性,比如颜色,位置,或者尺寸,还可以定义动画的某些特性,比如插值计算方法以及多个Animator的动画同步。

 

然而,组件动画设置简单,代码量小。如果组件动画可以满足你的需求,或者现有的代码已经是你想要的方式,那么就没有必要使用属性动画。如果实际情况发生变化的话,那么针对不同的情景,同时使用这两种动画系统也是比较合理的。

 

API预览

 

你可以在android.animation下面找到属性动画绝大部分的API。由于组件动画系统已经在android.view.animation下面定义了许多interpolator,你也可以在属性动画系统中使用这些interpolator。下表列出了属性动画系统中的重要组成部分。

 

Animator类提供了创建动画的基本结构。正常情况下,你不要直接使用这个类,因为它只提供最少的功能,只有通过扩展才能完全支持所有的动画设置。下面列出的都是Animator的子类:

表1. Animator

描述

ValueAnimator                                                                    

属性动画的主时间引擎,负责计算动画所作用对象属性的值。它包含了计算动画值的所有核心功能以及每个动画的时间细节信息,包括动画是否重复的信息,接收事件更新的监听器以及计算自定义类型数值的能力。动画作用于属性分2个部分:计算动画的值,然后将这些值设置到对象及其属性上。ValueAnimator并不执行第2部分,所以你必须监听ValueAnimator计算的值用来更新,然后用你自己的逻辑来修改动画作用的对象。关于更多信息,请查看小节“使用ValueAnimator来实现动画”。

ObjectAnimator

ValueAnimator的一个子类,它允许你设置动画作用的目标对象及其属性。当这个类计算出动画的新值时就会相应地更新属性值。大部分情况下你可能更想使用ObjectAnimator,因为它在计算目标对象的动画值时是非常容易的。然而,有时你会想直接使用ValueAnimator,因为ObjectAnimator有一些限制,比如需要目标对象提供某些属性的访问方法(译者:getXX/setXX方法)

AnimatorSet

提供一种机制来组合一些动画,这样它们运行时能够相互关联。你可以设置动画一起运行,顺序运行,或者有一定延迟。更多信息请参考小节“使用AnimatorSet来设计多个动画”。

Evaluator类告诉属性动画系统如何计算某个属性的值。它们接受Animator类提供的插分值,动画的开始值,结束值,然后基于这些数据计算最终的动画值。属性动画系统提供下列的Evaluator:

表2. Evaluator

/接口

描述

IntEvaluator

计算int型属性时使用的默认Evaluator

FloatEvaluator

计算float型属性时使用的默认Evaluator

ArgbEvaluator

计算16进制形式的颜色属性时使用的默认Evaluator

RectEvaluator(译者:原SDK文档没有此行)

计算Rect型属性时使用的 默认Evaluator

TypeEvaluator

一个允许你自定义Evaluator的接口。如果动画作用的对象属性既不是int, float,rect或者颜色型时,你必须实现TypeEvaluator接口来指定如何计算对象属性的动画值。你仍然可以为int, float, Rect或者颜色型的属性指定自定义的TypeEvaluator,如果你想为这些类型的属性计算提供不同于默认形式的行为。关于如何自定义Evaluator,请参考小节“使用一个TypeEvluator”。


一个时间插值器(Time Interpolator)定义了如何按照时间的函数方式来计算动画值。例如,你可以指定动画在整个动画期间按照线性方式进行,意味着在整个时间内动画是匀速移动的,或者你可以指定动画按非线性方式进行,比如,在开始时加速,结束时减速。表3列出了android.view.animation中包含的interpolator。如果下述中没有任何interpolator满足你的需求,那么你需要实现TimeInterpolator接口来创建自己的interpolator。关于如何自定义interpolator的更多信息,请参考小节“使用interpolator”。

表3. Interpolator

/接口

描述

AccelerateDecelerateInterpolator

一个在开始和结束时速度小而在中间速度大的Interpolator

AccelerateInterpolator

一个速度越来越大的Interpolator

AnticipateInterpolator

刚开始后退,然后向前冲

AnticipateOvershootInterpolator

刚开始后退,然后向前冲,越过终点,然后再后退到终点

BounceInterpolator

在终点处来回弹跳

CycleInterpolator

动画反复循环N次

DecelerateInterpolator

开始很快然后一直减速

LinearInterpolator

匀速运动

OvershootInterpolator

开始向前冲,越过终点然后返回到终点

TimeInterpolator

一个允许你实现自定义Interpolator的接口

 

使用ValueAnimator实现动画

 

ValueAnimator类允许你通过指定一组贯穿动画的int,float或颜色值来为某个时长的动画设置动画值。你可以通过调用ValueAnimator的工厂方法来获得一个ValueAnimator:ofInt(),ofFloat(),ofObject()。例如:

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

在上面的代码中,当start()方法运行时,那个ValueAnimator就会开始在1000ms的时长内,不断计算位于区间0到1的动画值。

 

你也像下面这样指定自定义的类型:

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

在这个代码里,当start()运行时,这个ValueAnimator开始计算在时长1000ms内,通过MyTypeEvaluator指定的逻辑来计算区间位于startPropertyValue到endPropertyValue的动画值。

 

前面的两个代码片段,实际上对某个对象没有实际效果,因为ValueAnimator并不会直接在某个对象或属性上操作。其实你最想做的事情应该是使用这些计算值来让动画作用于某个对象。你可以设置ValueAnimator的监听器,在整个动画的生命周期内适时地处理重要的事件,比如刷新帧。当实现了监听器后,为了获得某帧的动画值,你可以调用getAnimatedValue()。关于监听器的更多信息,请参考“动画监听器”部分。

 

使用ObjectAnimator实现动画

 

ObjectAnimator是ValueAnimator的子类(如前所述),它不但整合了ValueAnimator的时间引擎和数值计算功能,而且还能直接作用于目标对象的某个命名属性。这样对对象使用动画就变得很容易了,因为你不再需要实现ValueAnimator.AnimatorUpdateListener,动画作用的属性会自动更新。

 

实例化ObjectAnimator与实例化ValueAnimator很类似,但是除了设置动画值外,你还需要指定对象以及它的属性名字(字符串的形式):

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

 

为了使ObjectAnimator能正确自动更新属性,你必须做以下事情:

1.你要设置动画的对象属性必须有一个setter方法(以驼峰形式),形式为set<propertyName>()。因为ObjectAnimator在动画过程中自动更新属性,所以它必须能够通过setter方法访问属性。比如,如果属性名字为alpha,那么你必须有一个setAlpha()方法。如果这个setter方法不存在,你还有其他3个选择:

a.如果你有权限的话,在类中添加setter方法。

b.使用一个包装类,这样你就有权限修改它然后使这个包装类的setter方法收到动画值,然后传递给原始对象。

c.使用ValueAnimator来代替。

 

2.如果你为ObjectAnimator的工厂方法中的参数values…只提供一个值,那这个值就被认为是动画的结束值。如果是这样的话,你的设置动画的对象属性必须有一个getter方法,这样系统就能获得它的当前值来作为动画的初始值。getter方法的形式为get<propertyName>()。例如,如果属性名字为alpha,那么你必须有一个getAlpha()方法。

 

3.设置动画的属性的getter(如果需要的话)和setter方法操作参数类型必须与ObjectAnimator中指定的动画的开始及结束值类型一致。比如,你如果使用如下代码片段的ObjectAnimator的话,你必须有targetObject.setPropName(float)和targetObject.getPropName(float)方法:

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

4.取决于你设置动画的属性或对象,你可以需要调用View的invalidate()方法来强制屏幕使用新的动画值重新描画自身。你可以在onAnimationUpdate()回调中实现。比如说,在一个Drawable对象上的颜色属性上设置动画时,只能通过强制重新描画自身才能刷新屏幕。View上的所有属性设置方法,比如setAlpha()和setTranslationX()都会自动描画自身,所以你不需要再次调用View的invalidate()方法。关于监听器的更多信息,请参数小节“动画监听器”。

 

使用AnimatorSet来设计多个动画

 

在很多时候,你想播放的动画可能依赖于另一个动画是否开始或结束。安卓系统允许你使用一个AnimatorSet来组合多个动画,所以你可以决定是否同时开始动画,顺序动画或者等待某个延迟。你还可以在AnimatorSet中嵌入AnimatorSet。

 

下面的代码片段是从BouncingBalls的例子程序中提取的(为了简洁做了修改),按照下面的顺序播放Animator:

1.播放bounceAnim。

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

3.播放boundBackAnim。

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();

动画监听器

 

你可以使用下面列出的监听器来监听动画过程中的重要事件。

1.Animator.AnimatorListener

onAnimationStart() – 动画开始时调用。

onAnimationEnd() – 动画结束时调用。

onAnimationRepeat() – 动画反复时调用。

onAnimationCancel() – 动画取消时调用。不管一个动画是如何结束的,即使一个取消的动画仍然会调用onAnimationEnd()。

2.ValueAnimator.AnimatorUpdateListener

onAnimationUpdate() – 动画刷新每一帧时调用。监听这个事件可以使用ValueAnimator在动画过程中计算的数值。为了使用这个数值,你可以使用传递进来的ValueAnimator,调用它的getAnimatedValue()方法来获得这个数值。如果你使用了ValueAnimator,那么你需要实现这个监听。

根据设置动画的对象或属性,你可能需要在一个View对象上调用invalidate()方法来使用动画值强制描画自身。例如,对一个Drawable对象的颜色属性设置动画,只有当它重画自身的时候才会刷新屏幕。View上的所有属性setter方法,比如setAlpha()和setTranslationX()都会自动重画自身,因此当你使用动画新值调用这些方法的时候,无须再强制描画View对象。

 

如果你不想实现Animator.AnimatorListener中所有方法时,你可以继承AnimatorListenerAdapter类,而不用实现Animator.AnimatorListener接口。AnimatorListenerAdapter的实现方法都是空的,你可以选择性的覆写它。

 

例如,API Demos中的Bouncing Balls例子就使用了一个AnimatorListenerAdapter类,而且仅仅实现了onAnimationEnd()回调:

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对象提供简单的设置动画方式,而且也为ViewGroup的布局变化提供了设置动画的能力。

 

你可以使用LayoutTransition类为ViewGroup内的布局变化设置动画。当你在ViewGroup中添加或者移除View的时候,或者调用View的setVisibility()设置VISIBLE,INVISIBLE,GONE的时候,ViewGroup中的View就会在出现或消失时产生动画。当你添加或移除View的时候,ViewGroup中剩余的View也会动画移动到它们的新位置。你可以使用下面列出的几个LayoutTransition常量,传递给LayoutTransition的setAnimator()方法,再加上一个Animator对象,就可以定义这些常量对应的动画:

APPEARING– 标志一个动画,动画作用对象为容器中那些要显示的View。

CHANGE_APPEARING – 标志一个动画,动画作用对象为由于容器中有一个新的View要显示,而引起了变化的其他View。

DISAPPEARING – 标志一个动画,动画作用对象为容器中那些要消失的View。

CHANGE_DISAPPEARING – 标志一个动画,动画作用对象为由于容器中的某个View消失,而引起了变化的其他View。

 

你可以为以上4个事件定义你自己的动画来定制布局变化的外观,或者通知动画系统使用默认动画。

 

API Demos中的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" />

把这个属性设置为true,ViewGroup中那些添加或移除的View,以及剩余的View对象都自动被设置了动画。

 

使用TypeEvaluator

 

如果你要使用的动画类型是安卓系统未知的,那么你可以实现TypeEvaluator接口实现自己的evaluator。安卓系统已知的类型有int,float,颜色,Rect,这些类型依次被IntEvaluator,FloatEvaluator,ArgbEvaluator,RectEvaluator(API 18)支持。

 

TypeEvaluator接口中只有一个方法需要实现,即evaluate()方法。这个方法允许你的animator在当前的动画时间点为你的属性返回一个合适的值。下面的FloatEvaluator实现方法如下:

public class FloatEvaluator implements TypeEvaluator<Number> {    public Float evaluate(float fraction, Number startValue, Number endValue) {        float startFloat = startValue.floatValue();        return startFloat + fraction * (endValue.floatValue() - startFloat);    }}

注意:当ValueAnimator(或ObjectAnimator)运行时,它会计算动画的当时时间分数值(值位于0到1之间),然后根据你所使用的interpolator类型计算出插值分数。这个插值分数通过TypeEvaluator中的fraction参数传递给你,因此你计算动画值的时候不必考虑interpolator类型。

 

使用Interpolator

 

一个Interpolator定义了如何根据某个时间的函数来计算动画的值。例如,你可以指定在整个动画中使用线性运动,意思是在整个时间内做匀速运动,或者你可以指定动画使用非线性运动,比如在动画开始或结束时使用加速或减速运动。

 

Interpolator在动画系统中会从Animator中收到代表当前动画已经过去的时间的一个百分比小数值。Interpolator根据你设置的动画类型来修改这个分数。安卓系统在android.view.animation包下提供了一组通用的interpolator。如果这些都不符合你的需求,你可以实现TimeInterpolator接口,创建你自己的Interpolator。

 

作为一个例子,下面对比了默认的AccelerateDecelerateInterpolator和LinearInterpolator是如何计算插值分数的。LinearInterpolator对时间分数没有作任何修改。AccelerateDecelerateInterpolator加速进入动画,减速结束动画。下面的方法定义了这些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;}

下面列出了在1000ms时长的动画中使用上述的Interpolator计算出来的值:

过去的时间(毫秒)

时间分数/插值分数

(LinearInterpolator)

插值分数

(AccelerateDecelerateInterpolator)

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在200ms到600ms之间值的改变比LInearInterpolator要快,而在600ms到1000ms之间比它慢。

 

指定关键帧

 

一个Keyframe对象包含了一个时间/值对儿,允许你指定在动画的某个时间时的状态。每一个关键帧还可以使用自己的interpolator来控制在前一帧到本帧的这段时间内动画的行为。

 

为了初始化一个Keyframe对象,你必须使用它的某个工厂方法如ofInt(),ofFloat(),或ofObject()来获得一个合适的Keyframe类型。然后你再调用PropertyValuesHolder的工厂方法ofKeyframe()来获得一个PropertyValuesHolder对象。一旦你获得了这个对象,你可以通过传递这个PropertyValuesHolder对象和动画目标对象来获得一个Animator。下面的代码片段展示了如何做到这些:

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);

关于如何使用关键帧的更完整的例子,请参考APIDemo中的MultiPropertyAnimation例子。

 

为View设置动画

 

属性动画系统为View对象提供了高效流水线型的动画,而且相比组件动画系统提供了更多的优势。组件动画系统是通过View对象描画的方式来改变它们的。这些操作都是在每个View对象的容器中进行的,这些View本身并没有操作自己的属性。这样就导致了View虽然有了动画,但是View本身实际上没有任何变化。因此虽然View被描画在了屏幕上的另一个位置,但是它的事件仍然发生在它原来的位置。从安卓3.0开始,已经添加了一些新的属性和相关的setter和getter方法来消除这种缺陷。

 

属性动画系统通过实际改变View的属性值来实现View的动画。此外,当View的属性发生变化的时候,这些View会自动调用invalidate()方法来刷新屏幕。为了给属性动画提供便利,View类中新添加的属性有:

1.translationXtranslationY:这些属性控制View在布局容器中将要被放置的位置距当前左上坐标的偏差值。

2.rotationrotationX,和rotationY:这些属性控制围绕顶点进行的2维(rotate属性)和3维旋转。

3.scaleXscaleY:这些属性控制View围绕顶点进行的2维缩放。

4.pivotXpivotY:这些属性指定顶点的位置,用来作为旋转和缩放时的参考顶点。默认情况下,顶点位于对象的中心位置。

5.xy:这些属性属于实用型属性,指示了View在容器中的最终位置,等于左上值分别与translationX和translationY的和。

6.alpha:指示了View的透明度。默认值为1(不透明),0表示全透明(不可见)。

 

为了在View对象上属性设置动画,比如颜色或者旋转,你所需要做的就是创建一个属性animator,然后指定要动画的View的属性。比如:

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

使用ViewPropertyAnimator设置动画

 

ViewPropertyAnimator通过使用一个潜在的Animator对象,为在一个View对象上的几个属性上设置并行动画提供了一个很简单的方法。它的表现行为跟ObjectAnimator很像,因为它也是实际修改View的属性,但是它比同时设置多个动画属性更高效。此外,使用ViewPropertyAnimator的代码更简洁易读。下面的代码片段对比了使用多个ObjectAnimator对象,一个ObjectAnimator和ViewPropertyAnimator为一个View的x和y属性同时设置动画的不同:

使用多个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);

在XML中声明动画

 

属性动画系统允许你在XML中声明属性动画来代替代码。通过在XML中定义动画,你可以很轻松地在多个Activity中使用,而且更容易的更改动画的顺序。

 

为了区别使用新的属性动画API的动画文件和使用遗留的视图组件动画的文件,从安卓3.1开始,你应该在res/animator文件夹下面放置属性动画文件(而不是res/anim/)。使用animator文件夹是可选的,但是如果你想使用Eclipse ADT插件(ADT 11.0.0+)中的布局编辑工具的话,这样做却是必要的,因为ADT对于属性动画资源只会搜索res/animator文件夹。

 

下面的属性动画类在XML声明中使用如下的XML标签:

ValueAnimator --- <animator>

ObjectAnimator --- <objectAnimator>

AnimatorSet --- <set>

 

下面的例子按顺序播放两组对象动画,第1组同时播放两个对象动画:

<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对象中,然后在动画开始前设置目标对象。调用AnimatorSet的setTarget()方法可以设置一个动画目标对象。下面代码展示了如何做到这些:

AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext,    R.anim.property_animator);set.setTarget(myObject);set.start();


0 0