
概述
在Android中, 动画分为两种: Animation和Transition. 其中Animation分为View Animation和Property Animation.
Transition是用于Activity和Fragment的转场动画.
View Animation的作用对象是整个View对象, 它只支持4种动画效果: 平移, 缩放, 旋转和透明度动画. 另外, View Animation的一种特殊表现为: 逐帧动画. 它是通过缓慢的播放一组图像来到达一种动画效果. 需要注意的是: 由于逐帧动画是播放一组图像, 如果图片太大的话, 容易导致OOM.
Property Animation中文意思为: 属性动画. 它是Android 3.0推出的全新动画. 它主要是为了弥补View Animation的缺陷. View Animation只能支持View的四中动画. 除了这四种外的动画, View Animation都无能为力. 例如: 颜色的渐变动画.
下面主要总结一下Android中的属性动画.
动画的简单原理
假设现在有一个View, 它的X坐标为0. 如果我们想让它移动到X坐标为100的地方. 我们可以调用view.setTranslationX(). 但是出来的效果是: View在一瞬间跳跃到了100那里, 给人一种非常突然的感觉. 基于这种情况, 我们要让View移动到100的地方这个过程更符合人类的感官. 所以我们可以在一定的时间内, 每一帧改变View的位置, 当最后一帧的时候, 让View处于最终位置. 这样会比较符合人类的感官.
简单的来讲, 动画的整个过程可以这么概括: 给定一个动画完成的时间S, 动画每一帧的时间Sa, 根据经过的帧数来计算出动画完成的时间度(n*Sa / S). 接着根据这个时间完成度, 计算出动画完成度D. 最后根据D来计算出此时对应的属性为多少, 然后根据这个值来重新绘制.
时间完成度通过一个TimeInterpolator来计算出来动画的完成度. 而动画完成度通过TypeEvaluator计算出此刻的属性.
属性动画API
在使用属性动画时, 我们可以用这三个类:
ValueAnimator: 最基础的动画类, 它只负责根据时间完成度来计算出动画完成度. API最难使用, 但是最为灵活.ObjectAnimator:ValueAnimator的子类, 对ValueAnimator进一步的封装. 内部会根据传入的属性值来调用其对应的set和get方法来更新界面. API比较简单, 但是灵活性不如ValueAnimator.ViewPropertyAnimator: 针对Android View控件的动画的封装. 该类的使用场景: 多个动画需要同时进行. 该类内部会只调用一个重绘操作. 这也是该类的一个主要优化. 它的API调用最为简单. 但是只支持View的四种动画, 灵活性不大.
ViewPropertyAnimator
使用
ViewPropertyAnimator的使用最为简单:
- 执行单个动画:
|
|
- 多个动画同时执行:
|
|
由于ViewPropertyAnimator在播放多个动画时, 只支持同时播放, 所以播放同时播放多个动画时, 各个动画是共享Interpolator和播放时间的.
设置监听器
ViewPropertyAnimator支持设置三种类型的监听器:
ViewPropertyAnimator.setListener()ViewPropertyAnimator.setUpdateListener()ViewPropertyAnimator.withStartAction/EndAction()
|
|
|
|
|
|
适用场景
ViewPropertyAnimator的动画只支持View的四种动画. 还有只支持多个动画同时播放. 所以它的适用场景:
需要的动画类型为:
View的四种动画.(因此API调用简单)需要的是
View动画类型, 并且多个动画同时播放. (因此内部会只进行一次重绘的优化)
ObjectAnimator
如果你有一个自定义View, 它是一个自定义的圆形进度条. 你想对它的进度进行动画, 但是进度的类型为float, 因此, ViewPropertyAnimator不能胜任. 此时就要用ObjectAnimator了.
ObjectAnimator支持对任何类型值进行动画. 但是有一个前提: 在自定义View的内部添加setter和getter方法.
|
|
Interpolator
前面说过, Interpolator是计算动画完成度的依据. 它本质上是一个算法, 动画的完成度由时间完成度根据这个算法算出来的.
系统自带了它的很多子类. 这里不多说, 可以参考这篇文章
监听器
ObjectAnimator支持三种监听器
ObjectAnimator.addListener()ObjectAnimator.addUpdateListener()ObjectAnimator.addPauseListener()
|
|
|
|
|
|
适用场景
- 当动画类型不是
View的四种动画类型, 并且你有权利给你的View添加setter和getter
但是如果你没有权利给View添加setter和getter方法呢? 比如你正在用一个第三方的View. 这时候有两种选择:
用一个类来包装你的
View, 为包装View添加setter和getter方法.使用
ValuesAnimator来自己手动更新.
ValuesAnimator
ValuesAnimator是ViewPropertyAnimator和ObjectAnimator的父类, 这两个类都是对ValuesAnimator的进一步封装, 以此来提供更为便利的API调用. 因此这两个类的灵活性也下降了. 当上面的两个类都不能满足你的需求时, 你可以使用ValuesAnimator, 让它帮你计算每一帧后的属性值, 然后你监听这个属性的变化, 最后设置对应的属性, 并且重绘View.
|
|
从上面的代码, 我们发现, ValueAnimator的API调用相比前两个类, 要复杂一点, 但是它最为灵活. 前两个类只不过是对ValueAnimator的封装, 以便提供更为方便的API.
TypeEvaluator
TypeEvaluator为估值器, 前面说到, 算出动画的完成度后, 我们可以根据这个动画完成度来计算出当前属性的值. 那怎么算呢? TypeEvaluator就是来完成这个计算工作的.
在ObjectAnimator中, 我们常用的是ofInt和ofFloat方法, 但是如果你的属性是一个对象呢? 比如PointF对象, 这时, 应该使用ofObject方法.
下面以官方提供的一个PontFEvaluator为例.
|
|
多个属性的动画同时执行
ViewPropertyAnimator调用多个属性进行动画时, 是同时进行的. 那么对于ObjectAnimator呢? 它如何让多个属性进行配合? 答案是使用PropertyValuesHolder. 用法如下:
|
|
多个动画配合执行
有时候, 我们需要的效果可能是多个动画配合执行, 这时候, 我们可以用AnimatorSet.
|
|
总结
当你的动画类型是
View四种动画的其中一种或者两种以上的话, 优先使用ViewPropertyAnimator因为API调用很简单.当
ViewPropertyAnimator不能满足你的需求时, 使用ObjectAnimator.如果使用的
View的属性没有对应的setter和getter方法的话, 可以使用ValueAnimator.
参考资料
Android开发艺术探索