属性动画(Property Animation)框架可以弥补视图动画交互上的不足,实现更加丰富的动画效果。
在使用属性动画时,经常将ObjectAnimator和AnimatorSet配合使用,ObjectAnimator用来控制对象的一个属性值的变化,多个ObjectAnimator可以组合到AnimatorSet中,并且ObjectAnimator能够自驱动,还可以调用setFrameDelay()方法设置动画帧之间的间隙时间来调整帧率,减少频繁绘制达到节约CPU资源消耗的效果。
属性动画是通过调用属性的get、set方法真实地改变了View的属性值,所以,属性动画框架能满足在动画过程中的交互需求,实现基本上所有的动画效果。
ObjectAnimator
ObjectAnimator是属性框架中最重要的实行类,具体通过其静态工厂类进行创建。参数包括进行动画的对象和对象的属性名,这个属性必须要有get和set方法,因为ObjectAnimator会通过Java反射机制调用set方法修改属性值, 从而产生具体的动画效果。
下面利用ObjectAnimator实现一个简单的平移动画:
1 | ObjectAnimator animator = ObjectAnimator.ofFloat( |
在使用ObjectAnimator时,要注意需要操纵的属性必须要有get和set方法,下面是一些常用的可使用的属性值:
- translationX和translationY:控制View从坐标原点的偏移位置。
- rotation、rotationX和rotationY:控制View围绕支点进行旋转。
- scaleX和scaleY:控制View围绕支点进行缩放。
- pivotX和pivotY:控制View的支点位置,默认情况,支点位置时View的中心点。
- x和y:描述View在它的容器的最终位置,是最初的坐标位置与translationX和translationY的累计和。
- alpha:控制View的透明度。
视图动画的所有动画效果,都可以使用上面介绍的属性值实现。
如果View的某个属性没有提供get和set方法,也可以为其实现动画效果。具体有两种方案:一个是自定义属性类或包装类,间接地给属性增加get和set方法;另一个是通过ValueAnimator实现。ValueAnimator的具体使用在后面介绍,这里介绍如何使用前一种方法:
- 自定义包装类
1 | private static class WrapperView { |
- 操作包装类实现动画
1 | WrapperView wrapper = new WrapperView(view); |
PropertyValuesHolder
类似于视图动画中的AnimationSet,在属性动画中,如果要对同一个对象的多个属性同时产生动画,可以使用PropertyValuesHolder实现,具体使用如下:
1 | PropertyValuesHolder pvh1 = PropertyValuesHolder |
ValueAnimator
ValueAnimator是属性动画的核心类,ObjectAnimator就是它的子类。
ValueAnimator本身不提供任何动画效果,它像一个数值发生器,产生具有一定规律的数值,让调用者使用这些数值实现动画效果。
通常情况下,在ValueAnimator的AnimatorUpdateListener中监听数值变化,完成动画效果。具体使用如下:
1 | ValueAnimator animator = ValueAnimator.ofInt(200, 500); |
监听动画事件
属性动画的声明周期有Start、Repeat、End、Cancel四个过程,可以通过AnimatorListener监听这些事件:
1 | animator.addListener(new Animator.AnimatorListener() { |
大部分时候,我们只关心特定的事件,这时可以使用AnimatorListenerAdapter选择监听特定的事件:
1 | animator.addListener(new AnimatorListenerAdapter() { |
AnimatorSet
对于一个View同时作用多个属性动画效果,除了用前面介绍的PropertyValuesHolder实现,还可以用AnimatorSet实现,同时,AnimatorSet还可以对动画的播放顺序进行精确地控制。具体使用如下所示:
1 | ObjectAnimator animator1 = ObjectAnimator |
AnimatorSet可以使用playTogether()、playSequentially()、play()、with()、before()、after()方法控制多个动画协同工作,从而对动画播放顺序进行精确控制。
在XML中定义属性动画
属性动画同视图动画一样,可以直接在XML文件中定义,这样可以方便多个组件共享动画效果,具体代码如下所示:
1 | <?xml version="1.0" encoding="utf-8"?> |
定义完动画效果后,具体使用如下:
1 | Animator animator = AnimatorInflater |
ViewPropertyAnimator
可以使用ViewPropertyAnimator简化常用属性动画的使用,具体通过View的animate()方法实现,示例代码如下所示:
1 | view.animate() |
ViewPropertyAnimator、ObjectAnimator、ValueAnimator这三种Animator其实是一种递进的关系:从左到右依次变得更加难用,也更加灵活。它们的性能是一样的,因为ViewPropertyAnimator和ObjectAnimator的内部实现都是ValueAnimator。它们的差别只是使用的便捷性以及功能的灵活性。在实际使用时候的选择,只要遵循一个原则:尽量用简单的。能用View.animate()实现就不用ObjectAnimator,能用ObjectAnimator就不用ValueAnimator。
Interpolators
插值器(Interpolators)可以定义动画的变化速率,类似于物理学中的加速度,控制View的属性由起始值到目标值变化的方式。例如,对于位移动画,可以通过setInterpolator()方法设置AccelerateInterpolator,这样View的位移速度会越来越快。具体插值器的类别可以参考HenCoder的属性动画(上手篇)。