Android 动画机制总结
1.Android动画类型
1.1 Android动画类型分类
- 逐帧动画【Frame Animation】,即顺序播放事先做好的图像,跟电影类似
- 补间动画【Tween Animation】,即通过对场景里的对象不断做图像变换 ( 平移、缩放、旋转 ) 产生动画效果
- 属性动画【Property Animation】,补间动画增强版,支持对对象执行动画
- 过渡动画【Transition Animation】,实现Activity或View过渡动画效果
1.2 Android动画实现方式分类
- XML资源文件
- 代码方式
1.3 按照时间分类
- Android 3.0之前版本,逐帧动画,补间动画
- Android 3.0之后版本,属性动画
- Android 4.4中,过渡动画
2.Android逐帧动画
2.1 逐帧动画简单介绍
- 也叫Drawable Animation动画,是最简单最直观动画类型
2.2 逐帧动画XML资源文件方式
- 这个是最常用的方式,在res/drawable目录下新建动画XML文件,如下所示
- android:oneshot用来控制动画是否循环播放,true表示不会循环播放,false表示会循环播放
- android:duration=”200”表示每一帧持续播放的时间
1 | <?xml version="1.0" encoding="utf-8"?> |
2.3 逐帧动画代码方式
- 代码方式用的少,如下所示
1 | AnimationDrawable drawable = new AnimationDrawable(); |
3.Android补间动画
3.1 补间动画简单介绍
- 无需关注每一帧,只需要定义动画开始与结束两个关键帧,并指定动画变化的时间与方式等
- 主要有四种基本的效果
透明度变化
大小缩放变化
位移变化
旋转变化 - 表现形式
- XML中
1 | alph 渐变透明度动画效果 |
- JavaCode中
1 | AlphaAnimation 渐变透明度动画效果 |
3.2 差值器
- Android系统会在补间动画开始和结束关键帧之间插入渐变值,它依据差值器。
- Interpolator 时间插值类,定义动画变换的速度。能够实现alpha/scale/translate/rotate动画的加速、减速和重复等。Interpolator类其实是一个空接口,继承自TimeInterpolator,TimeInterpolator时间插值器允许动画进行非线性运动变换,如加速和限速等,该接口中只有接口中有一个方法 float getInterpolation(float input)这个方法。传入的值是一个0.0~1.0的值,返回值可以小于0.0也可以大于1.0。
- 提供几个Interpolator的实现类
1 | AccelerateInterpolator 加速,开始时慢中间加速 |
3.3 AplhaAnimation
- 第一种方式:XML方式,如下所示
1 | <?xml version="1.0" encoding="utf-8"?> |
- 第二种方式:代码方式
1 | AlphaAnimation alpha = new AlphaAnimation(0, 1); |
3.4 ScaleAnimation
- 第一种方式:XML资源文件方式
1 | <?xml version="1.0" encoding="utf-8"?> |
- 第二种方式:代码方式
1 | ScaleAnimation scale = new ScaleAnimation(1.0f, scaleXY, 1.0f, scaleXY, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); |
3.5 TranslateAnimation
- 第一种方式:XML资源文件方式
1 | <?xml version="1.0" encoding="utf-8"?> |
- 第二种方式:代码方式
1 | TranslateAnimation translate = new TranslateAnimation(fromXDelta, toXDelta, fromYDelta, toYDelta); |
3.6 RotateAnimation
- 第一种方式:XML方式
1 | <?xml version="1.0" encoding="utf-8"?> |
- 第二种方式:代码方式
1 | RotateAnimation rotate = new RotateAnimation(fromDegrees, toDegrees, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); |
3.7 自定义补间动画
4.Android属性动画
4.1 属性动画基本介绍
补间动画增强版本,补间动画存在一些缺点
a.作用对象局限:View 。即补间动画 只能够作用在视图View上,即只可以对一个Button、TextView、甚至是LinearLayout、或者其它继承自View的组件进行动画操作,但无法对非View的对象进行动画操作
b.没有改变View的属性,只是改变视觉效果
c.动画效果单一
属性动画特点
作用对象:任意 Java 对象,不再局限于 视图View对象
实现的动画效果:可自定义各种动画效果,不再局限于4种基本变换:平移、旋转、缩放 & 透明度
基本工作原理
在一定时间间隔内,通过不断对值进行改变,并不断将该值赋给对象的属性,从而实现该对象在该属性上的动画效果
属性动画基类:Animator,抽象类。子类有
两个重要的类:ValueAnimator 类 & ObjectAnimator 类
其他类:Evaluator类,AnimatorSet类
关于常用属性动画类总结如下图所示
4.2 Evaluator
- 估值器(TypeEvaluator)作用
- 设置动画 如何从初始值过渡到结束值的逻辑
- 插值器(Interpolator)决定值的变化模式(匀速、加速blabla)
- 估值器(TypeEvaluator)决定值的具体变化数值
- 看看接口TypeEvaluator 源代码
1 | public interface TypeEvaluator<T> { |
看看如何实现估值器
1 | public static ValueAnimator ofArgb(int... values) { |
4.3 AnimatorSet
- 特点
- 单一动画实现的效果相当有限,更多的使用场景是同时使用多种动画效果,即组合动画
- 使用方法
- 第一种方式:xml方式
1 | <?xml version="1.0" encoding="utf-8"?> |
- 第二种方式:Java方式
1 | // 步骤1:设置需要组合的动画效果 |
- 常用方法
1 | AnimatorSet.play(Animator anim) :播放当前动画 |
4.4 ValueAnimator
- 基本作用
- 将初始值 以整型数值的形式 过渡到结束值 。即估值器是整型估值器 - IntEvaluator
ValueAnimator.oFloat()采用默认的浮点型估值器 (FloatEvaluator)
ValueAnimator.ofInt()采用默认的整型估值器(IntEvaluator) - 第一种实现方式:Java设置
1 | public static ValueAnimator setValueAnimator(View view , int start , int end , int time , int delay , int count){ |
- 第二种实现方式:XML设置
1 | <?xml version="1.0" encoding="utf-8"?> |
4.5 ObjectAnimator
- 基本的原理
- 直接对对象的属性值进行改变操作,从而实现动画效果
继承自ValueAnimator类,即底层的动画实现机制是基于ValueAnimator类 - 第一种实现方式:Java设置
1 | public static ObjectAnimator setObjectAnimator(View view , String type , int start , int end , long time){ |
- 关于preperty的属性值有,如下表所示
- 第二种方式:XML方式
1 | <?xml version="1.0" encoding="utf-8"?> |
- 注意,以XML方式,res的文件夹名称必须是animator,否则无法引用,如下所示:
4.6 ValueAnimator与ObjectAnimator区别
- ValueAnimator 类是先改变值,然后手动赋值 给对象的属性从而实现动画;是间接对对象属性进行操作;
- ObjectAnimator 类是先改变值,然后自动赋值 给对象的属性从而实现动画;是直接对对象属性进行操作;
4.7 监听动画器
- 说明
- Animation类通过监听动画开始 / 结束 / 重复 / 取消时刻来进行一系列操作,如跳转页面等等
通过在Java代码里addListener()设置
因Animator类、AnimatorSet类、ValueAnimator、ObjectAnimator类存在继承关系,所以AnimatorSet类、ValueAnimator、ObjectAnimator都可以使用addListener()监听器进行动画监听 - 看看第一种监听方式
1 | mAnim.addListener(new Animator.AnimatorListener() { |
- 看看这二中监听方式
1 | mAnim2.addListener(new AnimatorListenerAdapter() { |
6.Android动画框架原理解析
6.1 关于补间动画原理
- 要了解Android动画是如何加载出来的,我们首先要了解Android View 是如何组织在一起的.每个窗口是一颗View树. RootView是DecorView,在布局文件中声明的布局都是DecorView的子View.是通过setContentView来设置进入窗口内容的. 因为View的布局就是一棵树.所以绘制的时候也是按照树形结构来遍历每个View进行绘制.ViewRoot.java中 draw函数准备好Canvas后 调用 mView.draw(canvas),这里的mView是DecorView.
- 下面看一下递归绘制的几个步骤:
- 1.绘制背景
- 2.如果需要,保存画布(canvas),为淡入淡出做准备
- 3.通过调用View.onDraw(canvas)绘制View本身的内容
- 4.通过 dispatchDraw(canvas)绘制自己的孩子,dispatchDraw->drawChild->child.draw(canvas) 这样的调用过程被用来保证每个子 View 的 draw 函数都被调用
- 5.如果需要,绘制淡入淡出相关的内容并恢复保存的画布所在的层(layer)
- 6.绘制修饰的内容(例如滚动条)
- 当一个 ChildView 要重画时,它会调用其成员函数 invalidate() 函数将通知其 ParentView 这个 ChildView 要重画,这个过程一直向上遍历到 ViewRoot,当 ViewRoot 收到这个通知后就会调用上面提到的 ViewRoot 中的 draw 函数从而完成绘制。Android 动画就是通过 ParentView 来不断调整 ChildView 的画布坐标系来实现的