Animation and Graphics

来源:互联网 发布:淘宝店公告栏图片 编辑:程序博客网 时间:2024/05/16 14:15
1.概述
 Android为UI元素的动画和自定义2D以及3D图形提供了多种功能强大的API。
 下面的章节大概地描述了这些API和系统的可用功能,依此来帮助你选择最合适的途径。


动画

Android系统提供了两种动画系统:属性动画(Property Animation Android3.0引入)和视图动画(View Animation补间动画)。这两种动画系统都是可行的方案,但是,在一般情况下,属性动画是你要优先考虑使用的。因为他更灵活,并提供了更多的功能。除了这两个动画系统,你同样可以利用Drawable动画,他可以允许你加载Drawable资源,然后一帧一帧地显示(帧动画)。

属性动画
在Android3.0中引入(API Level 11),利用属性动画系统你可以让任意一个对象的属性动起来,包括那些不会被渲染到屏幕上的对象。该系统是可扩展的,你可以自定义一个类型,并让其动起来。

视图动画(补间动画)
视图动画是一个旧的动画系统,他只能用在View类上。他比较容易使用,提供的功能也可以满足大多数应用的需求。

Drawable动画(帧动画)
帧动画逐帧显示视图资源,像一个胶卷一样。如果你的动画可以通过Drawable资源来展现的话,使用帧动画是很有用的。比如一个使用位图展示的进度。


2D和3D图形

在编写程序时,考虑清楚你对图形的需求是很重要的。不同的图形需求会有不同的技术来实现。比如,一个静态的应用和一个交互性的游戏相比,使用的图形动画技术是不同的。这里我们将讨论一些在Android中你可以选择的绘制图形技术,并说明那些任务适合他们。

Canvas and Drawables
Android系统提供了一套控件,可以为大部分的用户界面提供普遍性的功能。你同样可以继承这些控件来改变他们的外观和行为。此外,你可以通过Canvas类中提供的各种绘制方法自定义2D渲染,或者通过Drawable对象来创建更友好的按钮﹑逐帧运行的动画等。
此外,你可以通过Canvas类或者为更友好按钮、逐帧动画而创建的Drawable类中的各种绘制方法自定义2D渲染。

硬件加速
从Android3.0开始,你可以硬件加速大多数的Canvas API 完成的绘制,以进一步提高他们的性能。

OpenGL
通过Android系统API以及本地化的NDK,Android支持OpenGL ES 1.0 和2.0。当你想添加一些图形来增强你的应用,但是Canvas API又不支持,或者你希望平台独立性同时对性能的要求不是很高,这时使用系统API是可取的。和系统API相比NDK可以提供更高的性能支持,所以许多图形比较密集的应用如游戏,使用NDK是更好的选择(需要注意的是你依然可以通过系统API获取足够的性能。比如Google Body应用就是完全使用系统API开发)。如果你有大量的本地代码需要移植到Android上,通过NDK对OpenGL的支持 是更好的选择。如需了解使用NDK的更多信息,请阅读NDK下载后的docs /目录下的文档。 



2.属性动画
属性动画系统是一个强大的框架,它几乎可以为所有的对象定义动画。你可以定义一个随着时间推移,改变任意对象属性的动画,无论它是否绘制到屏幕上。属性动画在一个指定的时间长度上改变某个属性(对象中的一个字段)的值。定义动画,通过指定想要动起来的对象的属性,例如对象在屏幕上的位置,你想要多长时间的动画,动画值变化的区间。
属性动画系统允许你定义动画的以下特性:
  • 持续时间:你可以指定动画的持续时间,默认的长度是300毫秒。
  • 时间差值:你可以制定属性的值与动画耗时之间的函数关系。
  • 重复次数和行为:你可以定义当动画执行完毕后是否要重复,并指定重复次数。你同样可以设置动画是否可以反向播放。当设置它反向播放后动画会根据重复次数正向、反向循环播放。
  • 动画集合:你可以把一组动画定义到一个集合中,这样他们就能一起执行或者顺序执行。
  • 帧刷新延迟:你可以指定动画的帧多久刷新一次。默认是10毫秒刷新一次,但是你的应用程序真正的刷新速度最终由系统的整体速度和系统支持的底层计时器的速度决定。

 

属性动画如何工作


首先,让我们用一个简单的例子来看一下动画是如何工作的。图1描述了一个x属性设置动画的假象对象,x属性表示其在屏幕水平方向的位置。动画的持续时间设置为40毫秒,移动距离设置为40个像素。该对象每10毫秒(默认的帧刷新频率)在水平方向上移动10个像素。40毫秒动画结束后,该对象停留在水平方向40像素位置。这个例子中的动画使用一个线性的差值器,所以该对象的移动是匀速的。


图1 线性动画

 

你也可以为动画指定一个非线性的差值器。图2描述了在一个假象对象上定义了起始阶段是加速移动,结束时减速移动的动画。该对象仍然是40毫秒移动40像素,但为非线性移动。动画开始阶段加速移动到中间位置,接着从中间位置减速直到动画结束。图2展示了出,开始阶段和结束阶段的移动距离少于中间阶段。

 

图2 非线性动画

下面详细的介绍属性动画系统如何计算上图所示的那些动画,这是该系统的重要组成。图3描述主要类之间如何协调工作。


图3 如何计算动画

ValueAnimator对象会跟踪记录动画运行过程,如动画已经运行了多长时间,当前(被设置动画)属性的值。
 
ValueAnimator封装了TimeInterpolatorTypeEvaluator类型的对象,TimeInterpolator定义了动画的插值器,TypeEvaluator定义了如何计算动画属性的值。例如,在图2中,TimeInterpolator 设置为AccelerateDecelerateInterpolator ,TypeEvaluator设置为IntEvaluator。
 
创建动画,首先要创建一个ValueAnimator对象,然后设置开始阶段和结束阶段动画属性值,并指定动画的持续时间。调用start()动画开始启动。在整个动画运行过程中,ValueAnimator会计算动画的耗时因子( elapsed fraction),耗时因子在0-1之间,基于动画的持续时间和已经消耗的时间。耗时因子表示动画完成时间的百分比 ,0代表0%,1代表100%。例如,在图1中,在t=10毫秒时耗时因子等于0.25,因为总时间是40毫秒。
 
ValueAnimator 计算完耗时因子后,会调用当前设置的TimeInterpolator 对象去计算差值因子(interpolated fraction)。差值因子根据设置的TimeInterpolator将耗时因子转换成一个新的因子。例如在图2中,当t=10毫秒的时候,由于动画慢慢加速,差值因子为0.15小于耗时因子0.25。在图1中,差值因子和耗时因子总是一样的。
 
当差值因子计算完毕后,ValueAnimator 调用适当的TypeEvaluator,根据差值因子,开始值,结束值,计算当前阶段动画属性的值。例如在图2中,在t=10毫秒时,差值因子为0.15,动画属性的值此时就为0.15 ×(40 - 0)=6。
 
API DEMOS中提供了大量的例子演示了如何使用属性动画系统,请参阅包com.example.android.apis.animation。


属性动画和视图动画的区别


只有视图对象(View Object)才可以使用视图动画系统,因此当你想为非视图对象添加动画时,需要自己编码实现。视图动画系统事实上也存在局限性,他仅仅支持视图对象的几种表现形式,比如缩放和旋转View。

视图动画的缺点是他仅仅改变了View的绘画,但却没有改变View本身。举例来说,假如在屏幕上移动一个按钮,按钮的绘画位置是正确了,但是按钮点击的实际位置却没有改变,因此你还需要额外的逻辑处理。

在属性动画系统中,不仅没有这些限制条件,而且你还可以为任何的对象创建属性动画(View对象或者非View对象)并且对象本身是被真实修改的。属性动画系统在动画的支持上也更加的强大。更高水平上,设置颜色,位置,大小等属性动画的同时,也可以自定义动画的差值器,和编排同时运行的多个动画等。

但是视图动画系统可以花费更少的时间创建,当然编码也更少。如果视图动画可以满足你的所有需求,或者现有的代码也可以以你想要的方式在工作,那么就没有必要再使用属性动画系统。当然有些场景下你需要同时使用这两种动画系统。


API概览


大部分的属性动画API都在包 android.animation中。在包android.view.animation中视图动画系统定义了一些插值器,这些插值器在属性动画系统中也同样可以使用。下表中介绍了属性动画系统的主要组成部分。

Animator 类提供了创建动画的基本结构。通常不需要直接使用该类,因为他仅仅提供了一小部分功能。以下是Animator的子类:
              类                                                  描述ValueAnimator
属性动画的主要时间引擎,同时也负责计算动画的属性值。他具有计算动画值的所有核心功能,并记录每个动画的时间信息,包括动画是否重复,监听器是否收到更新事件,并且可以设置定义的TypeEvaluator。

运行的动画属性包括两个部分:计算动画的值以及为创建动画对象的属性上设置该值。ValueAnimator 并不进行第二项工作,所以你必须监听被ValueAnimator计算的属性值的更新,并依据自定义的逻辑更新动画对象。
ObjectAnimatorValueAnimator的子类,通过该类可以为动画设置目标对象和属性。当有新的值被计算出来时该类会更新属性的值。ObjectAnimator非常常用,因为他让为目标对象属性设置动画的过程变得非常简单。但是,有时你需要直接使用ValueAnimator,因为ObjectAnimator有更多的限制条件,如要求目标对象提供特定的访问器方法。AnimatorSet提供了一种机制使得一组动画可以一起运行。你可以设置多个动画一起运行,顺序运行或者在制定延迟后运行。

Evaluators(求值器)告知属性动画系统如何计算给定属性的值。他们使用Animator提供的时间数据和动画的起始结束值,以此计算动画的属性值。属性动画系统提供了以下的Evaluators:
         类/接口                                            描述                               IntEvaluator用以计算int类型属性值的默认求值器(Evaluators)FloatEvaluator用以计算float类型属性值的默认求值器(Evaluators)ArgbEvaluator用以计算十六进制颜色类型属性值的默认求值器(Evaluators)TypeEvaluator该接口允许自定义求值器。如果动画对象的属性值不是int,float,或者颜色类型的你必须通过实现TypeEvaluator接口来指定如何计算动画对象属性的值。如果希望和默认的计算方式不同,也可以为int,float,颜色指定自定义的TypeEvaluator。

时间插值器定义动画中指定的属性值在时间函数上如何被计算。比如,可以设置整个过程都是线性运行的动画,意味着动画是始终匀速运动的;或者设置一个非线性的动画,开始时加速,结束时减速的动画。下表中介绍了android.view.animation包中包含的插值器。如果没有插值器能满足你的需求,你就需要实现TimeInterpolator 接口自定义一个插值器。参阅Using interpolators来了解如何自定义插值器。
           类/接口                                                 描述                                         AccelerateDecelerateInterpolator 起始和结束速率较慢,中间加速的插值器AccelerateInterpolator 起始较慢然后加速的插值器AnticipateInterpolator 起始位置朝后移动,然后迅速甩出去的插值器AnticipateOvershootInterpolator 起始位置朝后移动,然后迅速甩出去,超过结束位置在弹回来的插值器 BounceInterpolator 在结束位置反弹的插值器 CycleInterpolator 指定的动画变化次数的插值器 DecelerateInterpolator 减速的插值器 LinearInterpolator 匀速 OvershootInterpolator 迅速冲过结束的位置然后弹回来的插值器 TimeInterpolator 插值器接口,可以自定义插值器


ValueAnimator的使用


通过ValueAnimator类你可以指定动画值的变化是int,float还是color类型的,并设置动画的持续时间。获取ValueAnimator通过工厂方法:ofInt()ofFloat(), or ofObject()。如下所示:
     ValueAnimator animation =ValueAnimator.ofFloat(0f,1f);      animation.setDuration(1000);     animation.start();
如上的代码中,当start()方法运行时,ValueAnimator开始计算动画的值,值的变化区间为0到1之间,持续时间为1000毫秒。

通过如下代码你可以为动画自定义一个类型
     ValueAnimator animation =ValueAnimator.ofObject(newMyTypeEvaluator(), startPropertyValue, endPropertyValue);     animation.setDuration(1000);     animation.start();
如上代码中,让start()方法启动时,ValueAnimator开始通过自定义的MyTypeEvaluator逻辑计算动画的值,值的变化区间是startPropertyValue到endPropertyValue,变化时间为1000毫秒。
前面代码片段,并没有真正的改变动画对象的值,因为ValueAnimator并没有直接的操作某个对象或者属性。你要做的事情就是将这些计算后的值设置到你的动画对象上。动画值的更新可以通过在ValueAnimator上设置监听器来实现,通过监听器你可以妥善的处理动画过程中的重要事件,如帧的更新等。设置好监听器后,你可以通过getAnimatedValue()来获取某一帧需刷新的动画值。了解更多的监听器信息,详见Animation Listeners。


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>()格式的set函数(驼峰大小写)。因为ObjectAnimator会调用该方法自动的更新属性的值,所以他也必须能访问该set方法。例如,属性的名称为foo,那么你必须有一个setFoo()的方法。如果这个setter方法不存在,你有三个选择: 
       1.如果你有权限的话可以为该类添加一个seeter方法
       2.使用一个你有权限的封装器,并且通过该封装器的一个setter方法接收动画值,并将该值更新到真正的动画对象上。
       3.改为使用ValueAnimator。
  • 如果你在ObjectAnimator工厂方法中设置的value... 参数只有一个值,则该值将被认为是动画的结束值。因此,动画对象的属性必须含有一个getter方法,通过该方法取出动画的开始值。getter方法也必须是get<propertyName>()格式的。比如,属性的名字是foo,那么他必须有个getFoo()的方法。
  • 动画属性的getter(如果需要的话)和setter方法必须是和动画的结束值和开始值是同一种类型。例如,如果构造ObjectAnimator是通过如下方式的话,你必须有一个targetObject.setPropName(float)和targetObject.getPropName(float)方法:
     ObjectAnimator.ofFloat(targetObject,"propName",1f)

  • 依赖于你的动画属性,你可能需要调用View的invalidate()方法以此来强制屏幕根据动画的值进行重绘。你通过onAnimationUpdate()回调方法来做这些事情。例如,在一个Drawable对象的color上设置动画,只有当屏幕重绘了才会促使他更新动画的值。View类中的所有的setter属性,如setAlpha()和setTranslationX()会调用View的invalidate()方法,所以当你通过这些方法来设置动画的值后不需要再调用invalidate()方法。


使用AnimatorSet编排多个动画


在大多数的情况下,你希望播放的动画可能依赖于另一动画的何时开始或者结束。Android系统允许你把多个动画一起绑定到AnimatorSet类中,你可以指定动画时并行,串行或者在指定时间后运行。你也可以将AnimatorSet对象相互嵌套。
以下的示例代码取自BouncingBalls例子,用下述的方式运行Animator对象:
  1. Plays bounceAnim.
  2. Plays squashAnim1squashAnim2stretchAnim1, and stretchAnim2 at the same time.
  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();



Animation Listeners


你可以通过如下描述的监听器来监听动画运行过程中重要的事件。
  • Animator.AnimatorListener
      1.onAnimationStart()    --     当动画启动时被调用
      2.onAnimationEnd()     --     当动画 结束时被调用
      3.onAnimationRepeat() --     当动画重复时被调用  
      4.onAnimationCancel() --     当动画被取消时被调用。被取消的动画同时也会调用onAnimationEnd(),不管他是如何被结束的。
  • ValueAnimator.AnimatorUpdateListener
      1.onAnimationUpdate()     --    每一帧的动画都会调用。监听此事件可以使用ValueAnimator计算后的动画值。该值的使用可以通过,事件传入的ValueAnimator对象的getAnimatedValue()方法获取。如果使用Valueanimator类那么实现该监听器是必须的。
           依赖于你的动画属性,你可能需要调用View的invalidate()方法以此来强制屏幕根据动画的值进行重绘。例如,在一个Drawable对象的color上设置动画,只有当屏幕重绘了才会促使他更新动画的值。View类中的所有的setter属性,如setAlpha()和setTranslationX()会调用View的invalidate()方法,所以当你通过这些方法来设置动画的值后不需要再调用invalidate()方法。
      如果你不需要实现所有Animator.AnimatorListener接口中的方法,你可以通过继承AnimatorListenerAdapter类来代替。AnimatorListenerAdapter类提供了方法的空实现,你可以选择性的覆盖他们。

例如,API演示中的跳跃球示例创建一个只用于onAnimationEnd()回调的AnimatorListenerAdapter。
     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());
}
  


为ViewGroup的布局变动设置动画(Animating Layout Changes to ViewGroups)


属性动画系统不仅仅为View对象同时也为ViewGroup提供了一套设置动画的简单方式。
你可以通过LayoutTransition 类为ViewGroup中布局的改变设置动画。在ViewGroup中的View会发生两种动作出现和消失,这两种动作的触发时机是当你在ViewGroup中add,remove一个View或者调用View.setVisibility()方法。ViewGroup中剩余的View也会动态的移动到他们的新位置。在这两动作发生的时候你可以通过LayoutTransition.setAnimator(int transitionType, Animator animator)方法为ViewGroup中的View设置动画(由animator参数指定),transitionType标识出ViewGroup中的哪些View会被应用该动画,描述如下:
  • APPEARING  动画应用到正要显示在容器中的Item上。
  • CHANGE_APPEARING  动画应用到由于新的Item显示而改变的Item上
  • DISAPPEARING 动画应用到正要从容器中消失的Iten上
  • CHANGE_DISAPPEARING 动画应用到由于新Item从容器中消失而改变的Item上
这四种类型的事件你都可以通过自定义动画来定制布局的转换方式,否则就是使用系统默认的动画。
APIDemo中的LayoutAnimations列子演示了如何为布局的过渡定义动画,然后为相应的View对象设置动画。
LayoutAnimationsByDefault类和相应的layout_animations_by_default.xml布局文件演示了如何在XML文件中为ViewGroup设置布局转换。你仅仅只需要将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后,被删除或者添加的View和ViewGroup中剩余的View都会自动的设置好动画。



使用TypeEvaluator

如果你想设置动画的类型在Android系统中不存在,你需要通过实现TypeEvaluator接口来创建你自己的求值器。Android系统中目前支持int(IntEvaluator),float(FloatEvaluator),color(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中接收到的fraction 参数就是差值因子,因此在你计算动画值的时候就不需要再考虑插值器了。



使用Interpolators

插值器定义了动画值在时间函数上如何被计算。例如,你可以定义一个线性的动画,意思就是动画在整个时间段内都是匀速运行的,也可以定义一个非线性的动画,比如,开始加速,结束减速的动画。
插值器从Animator中接收到的是耗时因子。插值器会根据它打算提供的动画类型修改耗时因子。系统中内置了一些差值因子,请查阅包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毫秒的动画使用上述两个插值器计算后动画的近似值:
      耗时(毫秒)         耗时因子和差值因子(Linear)        差值因子(Accelerate/Decelerate)0002000.20.14000.40.3456000.60.88000.80.910001.01.0
如上表所示,LinearInterpolator中值以相同的速度改变,每200毫秒改变0.2。AccelerateDecelerateInterpolator在200毫秒到600毫秒时间内值的改变快于LinearInterpolator,600毫秒到1000毫秒又慢于LinearInterpolator。



指定关键帧(Specifying Keyframes)

Keyframe 对象包含一个时间/值对允许你在动画的特定时间节点上制定一个特定的状态。每个Keyframe都可以有其自己的插值器来控制上一个Keyframe到该Keyframe事件间隔内动画的行为。
通过Keyframe的工厂方法 ofInt(),ofFloat(), or ofObject() 可以实例化一个Keyframe对象。然后调用工厂方法 ofKeyframe()获取PropertyValuesHolder 对象。获取该对象之后,你就通过传入PropertyValuesHolder和target(动画对象)参数来获取
Animator(ObjectAnimator)。如下例所示:
     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);
更多keyframes例子,参照APIDemo中的 MultiPropertyAnimation 。



为View设置动画(Animating View)

视图动画系统可以简化为View对象设置动画,和视图动画系统相比他也更有优势。视图动画系统通过改变View的绘画来实现View对象的动画。这些处理仅仅在View视图的容器中进行,因为VIew自己的属性并没有被操作。这样的结果就是View虽然被设置了动画,但是该对象本身并没有改变。比如虽然动画结束后他的绘画位置改变了,但是该对象真正的位置却没有改变。在Android3.0中,加入了新的属性和相应的getter,setter方法来解决这些缺点。
属性动画系统可以通过改变View对象的真实属性。此外,当他的属性改变时,View还可以自动的调用invalidate()方法去刷新界面。View类中便于使用属性动画的新属性有:
  • translationX and translationY:控制View的位置基于左上角坐标的偏移量。
  • rotation, rotationX, and rotationY:控制基于基准点的2D和3D旋转。
  • scaleX和scaleY:控制View基于基准点的二维缩放
  • pivotX and pivotY:控制视图的基准点,旋转和缩放都是基于基准点转换的。基准点的默认位置是对象的中心。
  • x和y:描述View在所在容器中的最终位置,是left,top和translationX,translationY的和。
  • alpha:描述View的透明度。默认是1(不透明),0代表透明(不可见)。
对View的属性设置动画,比如颜色变换,旋转变化,你所要做的就是创建一个Animator并且指定View的属性即可。例如:
     ObjectAnimator.ofFloat(myView,"rotation",0f,360f);

使用ViewPropertyAnimator(Animating with ViewPropertyAnimator)
通过使用一个底层的Animator对象,ViewPropertyAnimator提供了一种为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 =newAnimatorSet();     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文件中声明动画(Declaring Animators in XML)

属性动画系统不仅可以在代码中初始化,也可以在XML中配置。在XML中声明动画的好处是,你可以很方便在不同的Acitvity中重用动画,并且编排动画序列也很简单。
为了和View动画系统区分,从Android3.1开始,属性动画系统的的XML文件应该保存在res/animator/目录下(而不是/res/anim/)。使用animator目录是可选的,除非你希望使用ADT插件(11.0.0+)中的布局编辑器的话,因为ADT只搜索res/animator/中的属性动画资源。
下面列出了Animator的类和XML中标签的一一对应:
  • ValueAnimator  -  <animator>
  • ObjectAnimator -  <objectAnimator>
  • AnimatorSet    -  <set>

以下示例依次地播放两组对象动画集合,而第一个内嵌集合同时播放两个对象动画。

<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配置文件inflate到AnimatorSet对象中,然后在动画集合开始之前为所有的动画设置目标对象。
调用setTarget()可以为动画集合中所有的动画设置同一个目标对象。如下所示:
     AnimatorSetset=(AnimatorSet)AnimatorInflater.loadAnimator(myContext,         R.anim.property_animator);
     set.setTarget(myObject);
     set.start();



(完)
0 0
原创粉丝点击