安卓Property Animator动画详解(一)-官方文档

概览

安卓为UI元素和本身绘制2D、3D图形提供了一系列的API,这篇文章介绍了这些API的主要用法。javascript

动画

安卓框架提供了两种动画系统:属性动画(property animation)和视图动画(view animation)。两种动画效果均可以使用,可是一般状况下推荐使用属性动画(property animation),由于它更灵活而且有更多特性。除了这两种外,你还可使用帧动画(Drawable animation),这种动画使用图片资源逐帧展现。java

属性动画(property animation):

在安卓3.0(API11)引进,属性动画容许你对任何对象的属性进行动画处理,包括未在屏幕上展现的对象。属性动画能够扩展,而且容许你自定义属性。android

视图动画(View Animation)

视图动画只能用于views。相对来讲它能提供几乎知足你需求的全部动画。git

帧动画(Drawable Animation)

帧动画能够逐帧显示图片,就像电影同样。这种动画在你想要显示相似于进度一类的动画时是有用的。github

2D和3D图形

在编写应用程序时,重要的是要考虑你的图形需求是什么。不一样的图形任务最好用不一样的技术来完成。 例如,用于静态应用的图形和动画应当与用于交互式游戏的图形和动画不一样地实现。 在这里,咱们将讨论在Android上绘制图形的几个选项,以及它们最适合的任务。编程

画布和图片(Canvas and Drawables)

Android提供了一组View小部件,为各类用户界面提供了一些通用功能。 你还能够扩展这些小部件以修改它们的外观或行为方式。 此外,莫可使用Canvas类中包含的各类绘制方法来绘制本身的自定义2D渲染,或者为按钮或逐帧动画之类的内容建立Drawable对象。canvas

硬件加速

从安卓3.0引入,容许你是用硬件特性来更好的绘制你的画布。api

openGL

Android经过Android框架API以及本地开发工具包(NDK)能够支持支持OpenGL ES 1.0和2.0。当你想要为您的应用程序添加Canvas API不支持的一些图形加强功能时,或者您但愿独立于平台而且不要求高性能时,可使用安卓框架API。与NDK相比,使用框架API有一个性能损失,所以对于许多图形密集型应用程序,如游戏,使用NDK更好(重要的是,你仍然可使用框架API得到足够的性能。例如,Google Body应用程序彻底使用框架API开发)。若是你有不少本地代码,你想移植到Android,使用NDK的OpenGL也是有用的。框架

属性动画(Property Animation)

属性动画是一个强大的框架,几乎容许你为任何东西作动画。你能够定义随时间更改而改变对象属性的动画,而不用关心它是否是在屏幕上。属性动画在指定的时间内更改属性值。要设置动画,须要指定对象属性,例如对象在屏幕上的位置,设置时间,设置中间值。函数

属性动画中你能够指定下列特性:

  • Duration(过分时间) 定义动画的过渡时间,末日呢是300ms
  • Time interpolation 你能够指定计算属性的值做为动画当前已用时间的函数。
  • Repeat count and behavior 你能够指定是否在到达持续时间结束时重复动画,以及重复动画的次数。你还能够指定是否要反转播放动画。 将其设置为反向播放动画,而后反复向后播放,直到达到重复次数。
  • Animator sets 你能够将多个动画合为一组,包括同时播放、顺序播放或在指定延迟后播放的方式。
  • Frame refresh delay 你能够指定刷新频率,默认状况下是每10ms刷新一次,可是程序刷新频率取决于系统的总体忙碌程度。

属性动画是如何工做的

首先让咱们来看一个简单的例子:

图1描述了使用其X轴属性的动画对象,表示在屏幕上水平位置的移动。动画的持续时间40ms,行进距离40像素,这样每10ms水平移动10像素。图示的是线性插值动画,速度保持恒定。

图1

你也能够指定非线性插值方式。图2表示的是在动画开始时加速,动画结束时减速的动画过程。仍然是40ms移动40个像素,可是移动过程是非线性的。

图2

图3描述了动画的主要的类的彼此之间的工做

图3

ValueAnimator跟踪当前动画的时间,例如动画运行了多少时间,以及单签的属性值。

ValueAnimator封装了一个定义动画插值器的TimeInterpolator和定义TypeEvaluator。例如在图2中,使用的TimeInterpolator是AccelerateDecelerateInterpolator,使用的TypeEvalutor是IntEvaluator。

要启动动画,请建立ValueAnimator,并为其设置动画属性的起始值和结束值,以及动画的持续时间。 当你调用start()时,动画开始。在整个动画期间,ValueAnimator根据动画的持续时间和已通过去的时间,计算0和1之间的已过比例。 已过比例表示动画已完成的时间百分比,0表示0%,1表示100%。 例如,在图1中,在t = 10ms时的通过比例将是0.25,由于总持续时间是t = 40ms。

当ValueAnimator计算完已经完成的函数后,它调用当前设置的TimeInterpolator来计算接下来的插值函数。 插值函数将通过的函数映射到考虑了设置的时间新插值函数。 例如,在图2中,由于动画缓慢加速,因此插值函数(大约.15)小于通过的函数(.25),在t = 10ms。 在图1中,插值老是与通过的相同。

当计算插值函数时,ValueAnimator调用相应的TypeEvaluator,根据动画的插值函数,起始值和结束值计算你正在进行动画的属性的值。 例如,在图2中,插值函数在t = 10ms时为.15,所以此时的x轴属性值为.15 X(40 - 0)或6。

属性动画如何区别于视图动画

视图动画提供只对view对象进行处理的功能,所以若是你对非view进行动画处理,必须实现本身的代码。视图动画系统也受到约束,由于它仅将View对象的几个属性暴露给动画,例如视图的缩放和旋转,而没有背景颜色。

补间动画能够对View对象的内容执行一系列简单的变换(位置,大小,旋转和透明度)。因此,若是你有一个TextView对象,你能够移动,旋转,增加或收缩文本。 若是它有一个背景图像,背景图像将随文本一块儿变换。 动画包提供了补间动画中使用的全部类。

视图动画系统的另外一个缺点是,它只是在绘制视图时修改,而不是实际的View自己。例如,若是你使一个按钮在屏幕上移动,按钮移动绘制正确,可是你能够点击按钮的实际位置不会改变,因此你必须实现本身的逻辑来处理这个。

使用属性动画,上边提到的视图动画的缺点全都没有,你能够操做视图和非视图对象。属性动画在执行动画方式上也很好,你能够为要制做动画的属性(如颜色,位置或者大小)分配动画制做器,并能够定义动画的各个方面,例如多个动画制做工具的插值和同步。

然而,使用视图动画会比属性动画有较少的设置和代码编写。若是视图动画能知足你如今有的程序,就不须要使用属性动画,也能够结合二者使用。

API概览

Animators

在视图动画中已经定义了不少动画插值器,你也能够在属性动画中使用他们。Animator类为建立动画提供了一个基础框架,正常状况下你不不鞥使用这个类,它只提供了不多的功能,必需要经过继承来扩展它,下面是它的子类:

描述
ValueAnimator 属性动画的主要计时引擎,计算要须要使用动画的属性的值。它具备计算动画值并包含每一个动画的时间细节的全部的核心功能,关于动画是否重复执行的信息,接收更新时间的监听器以及设置自定义类型的能力。动画属性有两个部分:计算动画值,设置动画值。ValueAnimator不执行第二部分,所以你必须本身监听有ValueAnimator计算的值的更新,并修改逻辑对象。
ObjectAnimator ValueAnimator的子类,容许您将目标对象和对象属性设置为动画。 此类在为动画计算新值时相应地更新属性。 一般状况下使用ObjectAnimator,由于它使得对目标对象的动画过程更容易。 可是,你有时须要直接使用ValueAnimator,由于ObjectAnimator还有其余一些限制,例如须要在目标对象上存在特定的方法。
AnimatorSet 将一组动画有机的结合起来。你能够设置为同时播放,顺序播放,或者在指定延时后执行动画

Evaluators

Evaluators 告诉了属性动画如何根据给定的属性计算值。获取由Animator类提供的时间数据,动画的开始和结束值,并基于这些数据计算属性的值。如下是一些Evaluators:

类/接口 描述
IntEvaluator 默认的计算int型属性的Evaluator
FloatEvaluator 默认的计算float型属性的Evaluator
ArgbEvaluator 默认的计算颜色属性(16进制)的Evaluator
TypeEvaluator 一个容许你建立本身的Evaluator的接口。若是要对不是int,float或color的对象属性进行动画处理,则必须实现TypeEvaluator接口以指定如何计算对象属性的动画值。若是要处理那些类型与默认行为不一样,也能够为int,float和color值指定自定义TypeEvaluator。

时间插值器定义动画中的具体值如何对应时间的函数计算。例如,您能够指定动画在整个动画中线性发生,这意味着动画在整个时间内均匀移动,或者您能够指定动画以使用非线性时间,例如,在开始时加速,在结束时减速的动画。表3描述了android.view.animation中包含的内插器。 若是所提供的插值器都不适合您的须要,请实现TimeInterpolator接口并建立本身的插件。

Interpolators

类/接口 描述
AccelerateDecelerateInterpolator 开始和结束时慢,中间加速的插值器
AccelerateInterpolator 先缓慢后快速的加速器
AnticipateInterpolator 开始正向前而后反向的插值器
AnticipateOvershootInterpolator 先反向在正向超过目标值最后达到目标值
BounceInterpolator 在结束时反弹的插值器
CycleInterpolator 动画重复指定次数的周期插值器
DecelerateInterpolator 快速开始而后减速的插值器
LinearInterpolator 速度恒定的线性插值器
OvershootInterpolator 正向超过目标值而后返回目标值
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 ms。

您还能够经过执行如下操做,指定自定义动画:

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

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

然而,第一段代码片断对对象没有实际影响,由于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 形式的setter函数。由于ObjectAnimator在动画期间自动更新对象的属性,因此必须可以使用setter方法设置属性。例如,属性的名称是foo,则必须有一个setFoo()方法。若是此setter方法不存在,你能够按照下面的方法:

  • 能够的状况下将setter方法添加到类中
  • 若是你能够更改属性的包装类,可使包装类接受有效的setter方法,并将其转发到原始对象
  • 使用ValueAnimator类

若是你在ObjectAnimator工厂方法中的value的参数仅指定一个值,那么将会假定他是动画的结束值。所以你的对象属性必需要有一个getter方法,用于获取动画的起始值。gettter方法必须是get ()形式,例如若是属性的名称是foo,则须要getFoo()方法。你要动画的属性的getter和setter方法必须与你为ObjectAnimator指定的开始值和结束值操做相同的类型。例如,若是构造如下ObjectAnimator,则必须具备targetObject.setPropName(float)和targetObject.getPropName(float):

ObjectAnimator.ofFloat(targetObject,“propName”,1f)复制代码

根据你要动画化的属性或对象,你可能须要在视图上调用invalidate()方法,以强制屏幕使用更新的动画值重绘自己。你能够在onAnimationUpdate()回调中作到这一点。例如,对一个Drawable对象的颜色属性进行动画处理只会在该对象重绘自己时更新屏幕。 View上的全部设置的属性,例如setAlpha()和setTranslationX(),因此当使用新值调用这些方法时,您不须要使invalidate。
下面看几种效果:
1.AccelerateDecelerateInterpolator
效果:动画开始的时候慢速,慢慢加速,后边减速

2.AccelerateInterpolator
效果:动画慢慢加速,最后达到速度最快

3.AnticipateInterpolator
效果:先反向运动一段,而后正向运动


4.AnticipateOvershootInterpolator
效果:先反向运动一小段距离,而后超过终点一段距离,最后回到终点。

5.BounceInterpolator
效果:弹跳效果


6.CycleInterpolator
效果:循环完成屡次,在构造器中传入参数,这个参数就是循环的次数,中是例子2次


7.DecelerateInterpolator
效果:速度愈来愈慢


8.LinearInterpolator
效果:线性匀速运动


9.OvershootInterpolator
效果:超过终点而后返回

使用AnimatorSet编排多个动画

在多数状况下,你想在一个动画开始或者结束的时候启动另外一个动画,Android系统容许你将动画捆绑在一块儿成为AnimatorSet,以即可以指定是同时、按顺序启动动画仍是在指定的延迟后启动动画。 您还能够将AnimatorSet对象嵌套在彼此以内。

下面的例子是从Bouncing Balls中提取的一段代码,播放顺序以下:

  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();复制代码

下面看两个例子
1.按顺序播放动画

2.按顺序播放动画的同时播放透明度变化

Note:此处注意,在一个set中不能复用同一个动画

动画监听器

你能够在动画执行期间监听一些重要的事件。

Animator.AnimatorListener

  • onAnimationStart() 动画启动时调用
  • onAnimationEnd() 动画结束时调用
  • onAnimationRepeat() 动画重复时调用
    onAnimationCancel() 在动画被取消时调用,同时会调用onAnimationEnd(), 不管它是怎样被结束的。

ValueAnimator.AnimatorUpdateListener

  • onAnimationUpdate() 每一帧变化都会调用。用户监听此事件以使用动画期间ValueAnimator生成的计算值。 要使用该值,请查询传递到事件的ValueAnimator对象,以使用getAnimatedValue()方法获取当前的动画值。 若是使用ValueAnimator,则须要实现此侦听器。

根据你要动画化的属性或对象,你可能须要在控件上调用invalidate(),以强制屏幕的该区域使用新的动画值重绘自己。 例如,对一个Drawable对象的颜色属性进行动画处理只会在该对象重绘自己时更新屏幕。 View上的全部属性设置,例如setAlpha()和setTranslationX()使Viewinvalidate,因此当使用新值调用这些方法时,您不须要使调用invalidate。

若是不想实现Animator.AnimatorListener接口的全部方法,你能够扩展AnimatorListenerAdapter类,AnimatorListenerAdapter类提供了能够选择覆盖的方法的空实现。

例如,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的布局更改

属性动画系统可以为ViewGroup对象提供像对View对象同样简单的方法来制做动画。

你可使用LayoutTransition类在一个ViewGroup种使用动画来更改布局。当你为添加和删除的动做添加动画时,使用android.view.View.GONE,VISIBLE,INVISIBLE等或者调用set Visibility()方法设置可见不可见的时候,你能够调用setAnimator()并传入具备如下LayoutTransition常量的Animator对象,在LayoutTransiton种定义动画:

  • APPEARING - 一个在容器中添加item时候的动画的标记
  • CHANGE_APPEARING - 一个在容器中因为添加新的item而引发其余条目变化的动画标记
  • DISAPPEARING -一个在容器中消失的动画的标
  • CHANGE_DISAPPEARING - 一个因为某个item消失而引发的其余item变化的动画

API演示中的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接口建立本身的evaluator 。 Android系统已知的类型是int,float或color,它们由IntEvaluator,FloatEvaluator和ArgbEvaluator类型evaluator 支持。

在TypeEvaluator接口中只有一种方法,即evaluate()方法。这容许你使用的animator在动画的当前点为动画属性返回适当的值。 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);
    }
}复制代码

Note:当ValueAnimator(或ObjectAnimator)运行时,它计算动画的当前已过比例(0到1之间的值),而后根据你使用的插值器器计算插值号。 插值函数是你的TypeEvaluator经过fraction参数接收的,因此你没必要在计算动画值时考虑插值器。

使用Interpolators

插值器定义动画中的具体值与时间的函数关系。例如你能够指定动画在整个动画期间内线性运动,你也可使用非线性运动,加速和减速运动。

动画系统中的插值器从动画制做器接收表示动画的通过时间的函数。 插值器修依靠函数以与其目标提供的动画类型一致。 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的过程种对应的数值:

时间 Linear函数值 Accelerate/Decelerate函数值
0 0 0
200 .2 .1
400 .4 .345
600 .6 .8
800 .8 .9
1000 1 1

上表中能够看到,Linear是匀速运动,每200ms移动0.2。AccelerateDecelerateInterpolator是变速运动,200-600ms时加速很快,600-1000ms时变化慢。

定义关键帧

关键帧对象由时间/值的键值对组成,容许您在动画的特定时间定义特定状态。每一个关键帧也能够有本身的插值器,以控制动画在前一个关键帧的时间和该关键帧的时间之间的间隔中的行为。

要实例化一个Keyframe对象,必须使用ofInt(),ofFloat()或ofObject()的工厂方法之一来获取相应类型的关键帧。而后调用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);复制代码

控件动画

属性动画系统容许对View对象使用流线型动画,而且提供了超过视图动画系统的一些优势。 视图动画系统经过更改绘制对象的方式来转换视图对象。 这是在每一个View的容器中处理的,由于View自己没有可操做的属性。 这致使View被动画化,可是View对象自己没有改变。 这致使对象,即便它被绘制在屏幕上的不一样位置,仍然存在于其原始位置。在Android 3.0中,添加了新的属性和相应的getter和setter方法以消除此缺点。

属性动画系统能够经过更改View对象中的实际属性来在屏幕上更新View。 此外,View还会在其属性更改时自动调用invalidate()方法来刷新屏幕。 的View类中的新属性是:

  • translationX & translationY: 这些属性控制视图做为从其布局容器设置的左侧和顶部坐标的增量的位置。
  • rotation & rotationX & rotationY: 这些属性控制2D(旋转属性)中的旋转和围绕中心点3D的旋转。
  • scaleX and scaleY: 2D上控制缩放
  • pivotX and pivotY: 控制中心点的位置,围绕该点旋转和缩放变换。 默认状况下,该点位于对象的中心。
  • x and y: 用于在其容器中描述视图的最终位置,做为左侧值和顶部值以及translationX和translationY值的总和。
  • alpha: 描述View的透明度,0表示全透明,1表示不透明。

为了使View对象的属性拥有动画,例如他的颜色或者旋转角度,你要作的就是建立一个property animator对象而且指定你想要动画的属性。

ObjectAnimator.ofFloat(myView, "rotation", 0f, 360f);复制代码

ViewPropertyAnimator动画

使用ViewPropertyAnimator进行动画处理。ViewPropertyAnimator提供了一种简单的方法来使用单个底层Animator对象来并行地对视图的多个属性进行动画。 它的行为很是像一个ObjectAnimator,由于它修改View的属性的实际值,可是当同时对许多属性更有效。 此外,使用ViewPropertyAnimator的代码更简洁,更容易阅读。 如下代码片断显示了在同时对视图的x和y属性进行动画处理时,在使用多个ObjectAnimator对象,单个ObjectAnimator和ViewPropertyAnimator时的差别。

多个动画

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

单个动画

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中定义动画,您能够轻松地在多个活动中重复使用动画,并更轻松地编辑动画序列。

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

如下属性动画类具备如下XML标记的XML声明支持:

  • ValueAnimator -
  • ObjectAnimator -
  • AnimatorSet -

下面的例子是顺序播放两个动画,第一个动画集合中的两个动画是同时播放的:

<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();复制代码

最后附上github地址:
Demo

相关文章
相关标签/搜索