Property Animation(属性动画)

Posted yh_android_blog

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Property Animation(属性动画)相关的知识,希望对你有一定的参考价值。

概述

属性动画系统是一个强大的框架,它允许你将大多数东西动画化。你可以定义一个动画用来在动画播放的时候改变任何对象的属性值,而不管它在屏幕上有没有被绘制。属性动画在指定长度的时间内改变一个属性(对象的一个字段)的值。开始动画化一些东西,由你指定你想要动画化的对象属性,如一个在屏幕上的对象的属性,指定动画播放的时长,和在动画时改变成什么值。 属性动画系统会指导你如何去定义一个动画,只需要遵循如下步骤:
  • 持续时间:可以指定动画的持续时间,默认是300 ms 
  • 时间插值:可以在动画运行时通过一个函数来指定需要改变的属性值多久计算一次。
  • 重复次数和行为:当动画播放到末尾时,可以指定是否重复播放以及播放的次数。你还可以指定动画是否倒着播放。设置反向播放动画反复向前然后向后,直到达到重复出现的次数。
  • 动画设置:可以对动画进行逻辑分组,一起播放或顺序播放或指定延迟播放。
  • 帧刷新延迟:可以指定动画帧的刷新频率。默认值是每10ms 刷新一次,但是最终的刷新速度取决于你系统整体的繁忙度和响应时间。

 属性动画工作原理

首先,让我们通过一个简单的例子来了解动画是如何工作的。图1描述了一个假设的对象对它的x属性进行动画化,即它在屏幕上的水平位置。动画的持续时间设置为40ms 并且x增大了40像素。每10ms ,即默认帧刷新时间,该对象的水平距离就移动10像素。到最后的40ms时,动画停止,此时该对象的水平距离是40。这就是一个带有线性插值的动画,意味着该对象以一个恒定速度移动了。
图1.线性动画示例
你也可以将它设置为非线性的。图2说明了一个假想的对象在动画的前一段时间内加速,后一段时间内减速 的动画效果。该对象依旧是在40ms 中移动了40像素,但并非线性的。开始的一段时间,该动画加速至一半的点(即X=20),然后从这点开始减速,直到最后。如图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因为总的持续时间是40ms 。  ValueAnimator  计算完成了一个已播放分数,就会调用刚才设置的   TimeInterpolator  来计算插值分数( interpolated fraction )。一个插值分数将已播放分数映射到一个新的需要考虑时间插值的分数。例如,图2中,因为动画是逐渐加速的,在t=10ms 时,它的插值分数,大约是0.15,小于此时的已播放分数0.15。在图1,插值分数永远等于已播放分数。 当插值分数计算完成, ValueAnimator  调用适当的   TypeEvaluator ,来计算你需要动画化的属性的值,基于插值分数,开始值和结束值。例如,在图2中,t =10ms 时的插值分数是0.15,所以此时的属性值将会是0.15x (40 - 0),或者6。 com.example.android.apis.animation  包下的   API Demos 有许多关于如何使用属性动画系统的例子。

属性动画与视图动画的不同之处

视图动画系统仅仅提供了动画化view对象的能力,因此如果你想要动画化非view对象,只能由你自己去编码实现了。视图动画系统也是受限制的,因为它只公开了几个方面的动画视图对象,如对view的缩放和旋转,而没有背景颜色。 视图动画的另一个缺点是它只在View绘制时修改视图,并非真正修改view本身。例如,如果你实现一个 让一个按钮从左至右穿过屏幕 这样的一个动画,按钮会正确的绘制,但是它的实际位置是没有变化的,你还是可以在原来的位置点击它,所有你必须实现自己的逻辑来处理这个问题。 而属性动画系统,这些约束完全被移除了,并且你可以动画化任何对象(view 和非view)的任何属性,对象本身也确实被修改了。属性动画系统也用更健壮的方式执行动画。在更高层次上,你可以为你想要动画化的属性,如颜色,位置,或大小, 分配动画师,并且可以定义动画的各个方面,如插值和多个画师同步。 视图动画系统,然而,花费更少的时间来设置,需要更少的代码编写。如果视图动画完成了你需要做的一切,或者如果你现有的代码已经按你所期望的方式工作了,那就不需要使用属性动画系统了。如果用例出现了不同的情况,使用动画系统也是十分有意义的。

API 概述

android.animation .中可以找到最多的关于属性动画系统的API相关知识。因为在   android.view.animation  中已经定义了许多视图动画系统的插入器,你可以在属性动画系统中使用这些插入器。接下来的几张表格展示了属性动画系统的主要组件。
Animator 类提供了创建动画的基础结构。一般情况下你不必直接使用该类,它仅提供最小的功能,因此你必须继承它用以完全支持动画值。下面的这些子类都继承自 Animator

Table 1. Animators

Class Description
ValueAnimator  属性动画的主要计时引擎,也经常计算动画时的属性值。它具有所有的核心功能——计算动画值和包含每个动画的时间细节, 有关于动画何时重复播放的信息, 接收更新事件的监听器, 设置自定义的估计(evaluate)类型. 它主要有两个功能: 计算动画的值和在动画时为对象设置这些值。ValueAnimator 并不执行第二个功能, 因此你必须通过监听. ValueAnimator 计算出来的值的更新事件 来用你自己的逻辑修改你想要动画的对象的值。查看 #使用ValueAnimator制作动画部分获取更多消息。
ObjectAnimator  ValueAnimator 的一个子类,允许你设置目标对象和需要动画化的属性。  该类根据动画计算出来的新值来更新属性值. 大多数时候你需要用到 ObjectAnimator , 因为它使动画值用在目标对象上更加容易。然而,有些时候你必须直接使用ValueAnimator 因为ObjectAnimator 有一些限制,例如在目标对象上请求特定的存取方法。
AnimatorSet 提供一个组织动画的途径,这样你可以让它们通过一个顺序运行。例如一起播放,顺序播放,或延迟播放. 查看#使用AnimatorSet编排复合动画 章节获取更多信息。

求值器(Evaluator )告诉属性动画系统如何计算给定属性的值。它们通过 Animator 类来获取提供的时间数据,动画开始和结束的值,并且基于这些值计算动画时的属性值。属性动画系统支持如下求值器:

Table 2. Evaluators

Class/Interface Description
IntEvaluator 计算int 属性的默认求值器
FloatEvaluator 计算float 属性的默认求值器
ArgbEvaluator 计算颜色属性的默认求值器,是一个十六进制的值
TypeEvaluator 一个允许你创建自己的求值器的接口。 如果你要计算的对象属性值不在int,float,或颜色之中,你必须实现 TypeEvaluator 接口来指定如何计算动画属性值。你也可以为int,float,color指定一个自定义的求值器,如果不你想用默认方法的处理这些类型。查看 #使用TypeEvaluator章节获取更多信息

时间插值器(time interpolator)定义了一个时间函数如何在动画时计算一个特定的值。例如,你可以指定动画在整个动画时是线性发生的,意味着在整个时间内动画移动是匀速的。或者你可以指定为非线性的,例如在开始时加速,结束时减速。表3描述了包含在android.view.animation.中的插值器。如果这之中没有你需要的,实现TimeInterpolator接口来创建你自己的。查看#使用插值(Interpolators)来获取更多关于如何自定义插值器的知识。

Table 3. Interpolators

Class/Interface Description
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之间,持续时间是1000ms 。 你还可以为动画指定一个自定义类型,如下:
    
     
      ValueAnimator animation = ValueAnimator.ofObject(new MyTypeEvaluator(), startPropertyValue, endPropertyValue);
     
     
      animation.setDuration(1000);
     
     
      animation.start();
     
    
代码中,当start ()方法开始运行时, ValueAnimator  开始计算动画值,介于 startPropertyValue  和  endPropertyValue  之间,使用由 MyTypeEvaluator  提供的逻辑,持续时间1000ms 。
上面的代码片段,是的,在一些对象上是没有有实际作用的,因为 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>() setter函数。因为   Android 属性动画(Property Animation) 完全解析 (上)

Property Animation(属性动画)

属性动画-Property Animation之ViewPropertyAnimator 你应该知道的一切

Android 属性动画(Property Animation) 全然解析 (上)

Android Property Animation 属性动画

android中的动画之变换动画(Tween Animation)