Lihb +

Android属性动画

一、计算属性值

计算属性值

过程一:计算已完成动画分数 elapsed fraction 为了执行一个动画,你需要创建一个 ValueAnimator,并且指定目标对象属性的开始、结束值和持续时间。在调用 start 后的整个动画过程中, ValueAnimator 会根据已经完成的动画时间计算得到一个 0 到 1 之间的分数,代表该动画的已完成动画百分比。0 表示 0%,1 表示 100%。

过程二:计算插值(动画变化率)interpolated fraction 当 ValueAnimator 计算完已完成动画分数后,它会调用当前设置的 TimeInterpolator,去计算得到一个 interpolated(插值)分数,在计算过程中,已完成动画百分比会被加入到新的插值计算中。

过程三:计算属性值 当插值分数计算完成后,ValueAnimator 会根据插值分数调用合适的 TypeEvaluator 去计算运动中的属性值。

以上分析引入了两个概念:已完成动画分数(elapsed fraction)、插值分数( interpolated fraction )。

二、核心类介绍

核心类

2.1 Interpolators

插值器:时间的函数,定义了动画的变化律。

插值器只需实现一个方法:getInterpolation(float input),其作用就是把 0 到 1 的 elapsed fraction 变化映射到另一个 interpolated fraction。 Interpolator 接口的直接继承自TimeInterpolator,内部没有任何方法,而TimeInterpolator只有一个getInterpolation方法,所以所有的插值器只需实现getInterpolation方法即可。

2.2 Evaluators

Evaluators 告诉属性动画系统如何去计算一个属性值。它们通过 Animator 提供的动画的起始和结束值去计算一个动画的属性值。 属性系统提供了以下几种 Evaluators:

- IntEvaluator

- FloatEvaluator

- ArgbEvaluator

ps: 这三个由系统提供,分别用于计算 int,float,color 型(十六进制)属性的计算器

- TypeEvaluator

一个用于用户自定义计算器的接口,如果你的对象属性值类型,不是 int,float,或者 color 类型,你必须实现这个接口,去定义自己的数据类型。

TypeEvaluator接口只有一个方法,就是evaluate()方法,它允许你使用的 animator 返回一个当前动画点的属性值。

2.3 TimeInterpolator 和 TypeEvaluator 的区别

首先明确动画属性值的计算包括三步,其中第二步和第三步分别需要借助TimeInterpolator和TypeEvluator完成。

TypeEvaluator所做的是根据数据结构计算最终的属性值,允许你定义自己的数据结构,这是官方对它的真正定义,如果你所定义的属性值的数据类型不是 float、int、color 类型,那么你需要实现 TypeEvaluator 接口的evaluate()方法,自己进行属性值的计算

Interpolator更倾向于你定义一种运动的变化率,比如匀速、加速、减速等

小结

TypeEvaluator

定义了属性值的计算方式,有 int,float,color 类型,根据属性的开始、结束值和插值一起计算出当前时间的属性值,终极方法,整个动画属性值计算过程的结尾。

TimeInterpolation

插值器都必须实现的接口,定义了动画的变化率,如线性,非线性。

ValueAnimator与ObjectAnimator

两者都可以进行属性动画,但是ObjectAnimator更加简单,不用去做更新属性值的计算,但是必须要提供标准的setter和getter方法,让ObjectAnimator能够获取和更新属性值。

2.4 ViewPropertyAnimator

可以方便的为某个view多个属性添加并行的动画

下面的代码段分别展示了使用多个ObjectAnimator对象、一个ObjectAnimator对象、 ViewPropertyAnimator同时为一个 View 的 X 和 Y 属性添加动画的示例:

    **多个ObjectAnimator 结合 AnimatorSet实现**

    ```
    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 实现**
    
    ```
    PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("x", 50f); 
    PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("y", 100f); 
    ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvhY).start();
    
    ```
    ** ViewPropertyAnimator:只需要一行代码**
    
    ```
    myView.animate().x(50f).y(100f); //myView.animate()会直接返回一个ViewPropertyAnimator对象
    
    ```

2.5 PropertyValuesHolder

持有类的属性

2.6 KeyFrame

一个keyframe对象由一对 time / value 的键值对组成,可以为动画定义某一特定时间的特定状态。

每个keyframe可以拥有自己的插值器,用于控制前一帧和当前帧的时间间隔间内的动画。

Keyframe.ofFloat(0f,0f); 第一个参数为:要执行该帧动画的时间节点(elapsed time / duration)

第二个参数为属性值。

因此如果你想指定某一特定时间的特定状态,那么简单的使用 ObjectAnimator就满足不了你了,因为,ObjectAnimator.ofInt(….)类似的工厂方法,无法指定特定的时间点的状态。

三、View anim 与 Property anim 的比较

View anim 系统

view animation system 提供的能力只能够为 View 添加动画。因此如果你想为非 View 对象添加动画,就必须自己去实现, view animation system 在 View 动画的展现方面也是有约束的,只暴露了 View 的很少方面。比如 View 支持缩放和旋转,但不支持背景颜色的动画。

view animation system 的另一劣势是,其改变的是 View 的绘制效果,真正的 View 的属性保持不变,比如无论你在对话中如何缩放 Button 的大小,Button 的有效点击区域还是没有应用到动画时的区域,其位置与大小都不变。

但是 View animation system 只需花费很少时间创建而且只需很少的代码。如果 View 动画完成了你所有的动作,或者你存在的代码已经达到了你想要的效果,就没必要使用 property 动画系统了。

Property anim 系统

完全弥补了 View anim System 的缺陷,你可以为一个对象的任何属性添加动画,(View 或者非 View),同时对象自己也会被修改。 并且当属性变化的时候,property Anim 系统会自动的刷新屏幕。

属性动画系统在处理动画方面也更加强劲。更高级的,你可以指定动画的属性,比如颜色,位置,大小,定义动画的插值器并且同步多个动画。

并且在 Property Animation 中,改变的是对象的实际属性,如 Button 的缩放,Button 的位置与大小属性值都改变了。而且 Property Animation 不止可以应用于 View,还可以应用于任何对象。

平时使用的简单动画特效,使用 View 动画就可以满足,但是如果你想做的更加复杂,比如背景色的动画,或者不仅是 View,还希望对其它对象添加动画等,那么你就得考虑使用 Property 动画了。

四、参考文献

  1. 公共技术点之 Android 动画基础

  2. android 开发文档

点击查看评论

Blog

Knowledge

Project