Android动画
学习Android动画过程,参考了众大神的文章自己消化(见参考资料)整理的一篇笔记,仅作个人备忘。
一、动画概况
-
Frame Animation:
帧动画,顺序播放事先做好的图像,是一种画面转换动画。图片过多、过大容易产生OOM。
类 | 对应xml标签 |
---|---|
AnimationDrawable |
<animation-list><item/></animation-list> |

-
Tween Animation:
补间动画(又叫渐变动画),通过对场景里的对象不断做图像变换(平移translate、缩放scale、旋转rotate、透明度alpha)产生动画效果。
类 | 对应xml标签 |
---|---|
Animation |
<set></set> |
AlphaAnimation |
<alpha></alpha> |
ScaleAnimation |
<scale></scale> |
TranslateAnimation |
<translate></translate> |
RotateAnimation |
<rotate></rotate> |

-
Property Animation:
属性动画,通过动态地改变对象的属性从而达到动画效果,属性动画为API 11新特性。除了对View进行平移、缩放、旋转、透明度操作外,还可以将动画作用于指定的对象上。
类 | 对应xml标签 |
---|---|
Animator |
<set></set> |
ObjectAnimator |
<objectAnimator></objectAnimator> |
ValueAnimator |
<animator></animator> |

注意:
- 属性动画在3.0之后支持,之前的需要使用兼容库。
- 属性动画可以真正改变View的位置,而View动画则只在视觉上进行移动,实际位置并未改变。
- 属性动画属于Animator框架,补间动画属于Animation框架,帧动画属于Drawable框架。
二、概念理解
- 时间插值器
对于补间动画:时间插值器(TimeInterpolator)的作用是根据时间流逝的百分比计算出动画进度的百分比。根据百分比计算出动画开始的关键帧与将要显示的帧之间的差异(通过Transformation类的对象表示)。
对于属性动画:时间插值器(TimeInterpolator)的作用是根据时间流逝的百分比计算出动画进度的百分比(即属性值改变的百分比)。
常用的时间插值器对应的类与时间插值器(TimeInterpolator)之间的继承关系图

- 类型估值器
类型估值器(TypeEvaluator)的作用是根据属性值改变的百分比计算出改变后的属性值(针对属性动画框架,View动画框架是不需要类型估值器的)。
属性动画实际上作用的是对象的属性,而属性的类型是不同的,因此Android内置了一些常用的类型估值器来操作不同类型的属性:

- 动画工作原理
属性动画框架工作原理可以总结为如下三步:
-
在创建属性动画时如果没有设置属性的初始值,此时Android系统就会通过该属性的get方法获取初始值,所以在没有设置属性的初始值时,必须提供该属性的get方法,否者程序会Crash。
-
在动画播放的过程中,属性动画框架会利用时间流逝的百分比获取属性值改变的百分比(即通过时间插值器),接着利用获取的属性值改变的百分比获取改变后的属性值(即通过类型估值器)。
-
通过该属性的set方法将改变后的属性值设置到对象中。
只要某个类具有属性(即该类含有某个字段的set和get方法),那么属性动画框架就可以对该类的对象进行动画操作(其实就是通过反射技术来获取和执行属性的get,set方法),因此属性动画框架可以实现View动画框架的所有动画效果并且还能实现View动画框架无法实现的动画效果。
- 动画插值计算
属性动画最关键的部分就是值得计算,下图是计算的过程:

计算过程分为三个阶段:
- 计算已完成分数。为了执行一个动画,你需要创建一个 ValueAnimator,并且指定目标对象属性的开始、结束值和持续时间。在调用 start 后的整个动画过程中, ValueAnimator 会根据已经完成的动画时间计算得到一个 0 到 1 之间的分数,代表该动画的已完成动画百分比。0 表示 0%,1 表示 100%。
- 计算插值(动画变化率)。 当 ValueAnimator 计算完已完成动画分数后,它会调用当前设置的 TimeInterpolator,去计算得到一个 interpolated(插值)分数,在计算过程中,已完成动画百分比会被加入到新的插值计算中。
- 计算属性值。当插值分数计算完成后,ValueAnimator 会根据插值分数调用合适的 TypeEvaluator 去计算运动中的属性值。
以上分析引入了两个概念:已完成分数(elapsed fraction)、插值分数( interpolated fraction )。
三、使用示例
- Frame Animation:
xml方式实现
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="true">//
<item android:drawable="@mipmap/icon1" android:duration="300"/>
<item android:drawable="@mipmap/icon2" android:duration="300"/>
<item android:drawable="@mipmap/icon3" android:duration="300"/>
<item android:drawable="@mipmap/icon4" android:duration="300"/>
<item android:drawable="@mipmap/icon5" android:duration="300"/>
<item android:drawable="@mipmap/icon6" android:duration="300"/>
<item android:drawable="@mipmap/icon7" android:duration="300"/>
<item android:drawable="@mipmap/icon8" android:duration="300"/>
<item android:drawable="@mipmap/icon9" android:duration="300"/>
</animation-list>
java方式实现
view.setImageResource(R.drawable.icons);
AnimationDrawable animationDrawable = (AnimationDrawable) view.getDrawable();
animationDrawable.start();
- Tween Animation:
xml方式实现
<!-- View向上平移自身高度距离 -->
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="2000"
android:fillAfter="true"
android:fromXDelta="0%"
android:fromYDelta="0%"
android:toXDelta="0%"
android:toYDelta="-100%" />
java方式实现
//View右移100像素
TranslateAnimation translateAnimation = new TranslateAnimation(0f, 0f, 0f, 100f);
translateAnimation.setDuration(2000);//动画的持续时间,单位毫秒
translateAnimation.setFillAfter(true);//参数为true表示动画结束后View停留在结束为止
view.startAnimation(translateAnimation);//开始动画
- Property Animation:
xml方式实现
<!-- View0到50平滑过渡的效果 -->
<?xml version="1.0" encoding="utf-8"?>
<animator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="2000"
android:valueFrom="0"
android:valueTo="50"
android:valueType="floatType" />
java方式实现
//View右移出屏幕再回来
float translationX = view.getTranslationX();
ObjectAnimator animator = ObjectAnimator.ofFloat(view, "translationX", translationX, 600f, translationX);
animator.setDuration(3000);
animator.start();
四、参考资料
-
Android 动画基础
(@lightsky 大神)
-
Android属性动画完全解析(下),Interpolator和ViewPropertyAnimator的用法
(@郭林 大神)
-
Android 属性动画(Property Animation) 完全解析 (上)
(@鸿洋 大神)
-
Android应用开发之所有动画使用详解
(@工匠若水 大神)