2019独角兽企业重金招聘Python工程师标准>>>

作者: 刘鹏
日期: 2009-03-07
Android 平台提供了两类动画,一类是 Tween 动画,即通过对场景里的对象不断做图像变换(平移、缩放、旋转)产生动画效果;第二类是 Frame 动画,即顺序播放事先做好的图像,跟电影类似。本文分析了 Tween 动画的实现原理。

主要思路

Tween 动画通过对 View 的内容完成一系列的图形变换 (包括平移、缩放、旋转、改变透明度)来实现动画效果。

具体来讲,预先定义一组指令,这些指令指定了图形变换的类型、触发时间、持续时间。这些指令可以是以 XML 文件方式定义,也可以是以源代码方式定义。程序沿着时间线执行这些指令就可以实现动画效果。

动画的进度使用 Interpolator 控制,android 提供了几个 Interpolator 子类,实现了不同的速度曲线,如LinearInterpolator 实现了匀速效果、 Accelerateinterpolator 实现了加速效果、DecelerateInterpolator 实现了减速效果等。还可以定义自己的 Interpolator 子类,实现抛物线、自由落体等物理效果。

动画的运行模式有两种:

  • 独占模式,即程序主线程进入一个循环,根据动画指令不断刷新屏幕,直到动画结束;
  • 中断模式,即有单独一个线程对时间计数,每隔一定的时间向主线程发通知,主线程接到通知后更新屏幕;

图形变换通过仿射矩阵实现。图形变换是图形学中的基本知识。简单来说就是,每种变换都是一次矩阵运算。在 Android 中,Canvas 类中包含当前矩阵,当调用 Canvas.drawBitmap (bmp, x, y, Paint) 绘制时,android 会先把 bmp 做一次矩阵运算,然后将运算的结果显示在 Canvas 上。这样,编程人员只需不断修改 Canvas 的矩阵并刷新屏幕,View 里的对象就会不停的做图形变换,动画就形成了。

在 android 中提供了 Animation 、 Interpolator、Transformation 等类具体实现 Tween 动画,下面逐一分析。

Animation 类及其子类

Animation 类及其子类是动画的核心模块,它实现了各种动画效果,如平移、缩放、旋转、改变透明度等。

Tween 动画的每一桢都根据 Interpolator 对 view 的内容做一次图形变换,因此 Animation 的核心工作是做变换(transformation)。

Aniamtion 是基类,他记录了动画的通用属性和方法。主要的属性包括动画持续时间、重复次数、interpolator 等。动画里最重要的方法是 getTransformation (currentTime, outTransformation),该方法根据当前间 (currentTime) 和 interpolator,计算当前的变换,在 outTransformation 中返回。

TranslateAnimation、RotateAnimation、AlphaAnimation 等是 Animation 的子类,分别实现了平移、旋转、改变 Alpha 值等动画。

每个动画都重载了父类的 applyTransformation 方法,这个方法会被父类的 getTransformation 方法调用。另外每个动画还有个 initialize 方法,完成初始化工作。

不同的动画具有不同的属性,如 RotateAnimation 的属性是起始角度、终止角度和旋转点坐标, TranslateAnimation 的属性是起始位置和终止位置。AlphaAnimation 的属性是起始 alpha 值和终止 alpha 值。

Animation 类及其子类的类图如下所示:

android类及其子类

Interpolator 类及其子类

Interpolator 定义了动画的变化速度,可以实现匀速、正加速、负加速、无规则变加速等;

Interpolator 是基类,封装了所有 Interpolator 的共同方法,它只有一个方法,即 getInterpolation (float input),该方法 maps a point on the timeline to a multiplier to be applied to the transformations of an animation.

LinearInerpolator、AccelerateInterpolator, DecelerateInterpolator, AccelerateDecelerateInterpolator,CycleInterpolator 是 Interpolator 的子类,分别实现了匀速、加速、减速、变速、循环等效果。

对于 LinearInterpolator ,变化率是个常数,即 f (x) = x.

public float getInterpolation(float input) {return input;}

对于 AccelerateInterpolator,开始变化很慢,然后逐渐变快,即 f(x) = x*x 或者 f(x) = pow(x, 2*mFactor).

public float getInterpolation(float input) {if (mFactor == 1.0f) {return (float)(input * input);} else {return (float)Math.pow(input, 2 * mFactor);}}

对于 AccelerateDecelerateInterpolator,变化率开始和结束都很慢,但中间很快,即 f(x) = (cos ((x+1)*PI) / 2.0f) + 0.5f.

public float getInterpolation(float input) {return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;}

Interpolator 类及其子类的类图如下所示:

Interpolator 类及其子类

Transformation 类

Transformation 记录了仿射矩阵 Matrix,动画每触发一次,会对原来的矩阵做一次运算, View 的 Bitmap 与这个矩阵相乘就可实现相应的操作(旋转、平移、缩放等)。

Transformation 类封装了矩阵和 alpha 值,它有两个重要的成员,一是 mMatrix,二是 mAlpha。

Transformation 类图如下所示:

Transformation 类图

如何在 View 中实现动画

从逻辑上讲,实现动画需要如下几步:

  1. view 创建动画对象,设置动画属性,调用 invalidate 刷新屏幕,启动动画;
  2. invalidate 方法触发了 onDraw 函数;
  3. 在 onDraw 函数中:
    • 调用动画的 getTransformation 方法,得到当前时间点的矩阵
    • 将该矩阵设置成 Canvas 的当前矩阵
    • 调用 canvas 的 drawBitmap 方法,绘制屏幕。
    • 判断 getTransformation 的返回值,若为真,调用 invalidate 方法,刷新屏幕进入下一桢;若为假,说明动画完成。

整个流程可用一个序列图表示:

Tween 动画序列图

使用样例

下面的代码是一个 view,系统创建 view 时会调用 onCreate 方法,该方法定义了一个 TranslateAniamtion,指定了移动起点和终点,动画持续时间为 1s,最后调用 startAnimation 将该动画保存在 View 的成员 mCurrentAnianmtion 中并启动动画。

注意,在 View 中需要定义成员变量 mCurrentAnimation 和 mTransformation ,分别记录当前的动画和变换。另外需要定义成员函数 startAnimation 启动动画。

class MyView extends View {

Animation mCurrentAnimation  = null;

Transformation mTransformation = new Transformation;

private void setAnimation(Animation animation) {
        mCurrentAnimation = animation;
        if (animation != null) {
            animation.reset();
        }
    }

public void startAnimation(Animation animation) {
        animation.setStartTime(animation.START_ON_FIRST_FRAME);
        setAnimation(animation);
        invalidate();
    }

onDraw (Canvas canvas) {

long curTime = SystemClock.uptimeMillis ();

if (mCurrentAniamtion == null){

canvas.drawBitmap (b, x, y, mPaint);

}

else {

if (!mCurrentAnimation.isInitialized())  //initialize animation

mCurrentAnimation.initialize (w, h, pw, ph);

boolean more = mCurrentAnimation.getTransformation (curTime, mTransformation);

if(more) {

Matrix m = canvas.getMatrix();

canvas.setMatrix (mTransformation.getMatrix());

canvas.drawBitmap (b, x, y, mPaint);

canvas.setMatrix (m);

this.invalidate ();

}

else {

mCurrentAnimation = null;

this.invalidate ();

}

}

}

void onCreate (){

Animation anim = new TranslateAnimation (10, 20, 0, 0);

anim.setDuration (1000); // 1s

anim.setInterpolator (new AcceleratInterpolator(3.0f));

startAniamtion (anim);

}

}

原文:http://www.linuxgraphics.cn/animation/android_tween_animation.html

转载于:https://my.oschina.net/kevin008/blog/2195

分析android动画模块[转]相关推荐

  1. 分析android动画模块

    Android 平台提供了两类动画,一类是 Tween 动画,即通过对场景里的对象不断做图像变换(平移.缩放.旋转)产生动画效果:第二类是Frame 动画,即顺序播放事先做好的图像,跟电影类似.本文分 ...

  2. android4.2 音频模块启动分析,Android 音频模块学习小结

    现在移动端已不仅仅局限于文本.图片这些 pc 平台上的常见信息类型,语音的使用愈见频繁,于是前段时间萌生了个想法:如果在移动端对语音内容做处理,提取特征出来构建关键词库是否可以对这些语音进行分类.搜索 ...

  3. Android 动画之ScaleAnimation应用详解

    本节讲解ScaleAnimation 动画在应用中的实现,有需要的朋友可以参考下 android中提供了4中动画: AlphaAnimation 透明度动画效果 ScaleAnimation 缩放动画 ...

  4. android 补间动画有停顿,Android动画原理分析(一)----补间动画

    1.基本特点 补间动画(Tween动画),是android最早的动画框架,从Android1.0开始就有. 功能:可以实现移动.旋转.缩放.渐变四种效果以及这四种效果的组合形式. 实现形式:xml和代 ...

  5. android 动画卡顿分析工具

    android 动画卡顿分析工具 Android应用性能优化之分析工具 上一次记录了解决过度绘制的过程,这一次,想先弄清个概念性的东西,就是如何判断顺不顺畅? 这东西其实最初我自己也觉得有点废话,用起 ...

  6. Android属性动画赏析,Android源码分析—属性动画的工作原理

    前言 本文为Android动画系列的最后一篇文章,通过对源码的分析,能够让大家更深刻地理解属性动画的工作原理,这有助于我们更好地使用属性动画.但是,由于动画的底层实现已经深入到jni层,并且涉及到显示 ...

  7. Android GNSS 模块分析(四)HAL 层

    紧接着上一篇(Android GNSS 模块分析(三)JNI 层),继续来分析下 Android GNSS HAL 层的功能,本篇准备先介绍下 HIDL 层的封装.至于后面的 HAL 层的功能,由于使 ...

  8. Android动画了解—一些项目案例分析

    文章目录 写在前面 带路径运动的过渡动画 整体缩放的效果 整体宽高改变的过渡效果 两个界面布局的过渡效果 带水波纹布局的效果 几行代码实现转圈圈的效果 界面翻转的效果 写在前面 最近听说MIUI 12 ...

  9. Android GNSS 模块分析(五)NMEA 协议

    紧接着上一篇<Android GNSS 模块分析(四)HAL 层>,本篇简述下导航硬件设备与卫星导航系统之间的通信协议. NMEA 协议 简介: NMEA(National Marine ...

最新文章

  1. 服务器负载均衡(1)
  2. wxWidgets:wxClipboardTextEvent类用法
  3. Java不同压缩算法的性能比较
  4. N小时改变一次url时间戳的方法
  5. Windows平台下Android源码的下载(Z)
  6. css --- 手机端,留言模块的样式
  7. 前端学习(2800):实现news-item的封装
  8. 用户思维模型,围绕用户核心四大模块,拉新、养熟、成交、裂变循环的效果...
  9. hadoop jar包_Hadoop学习之路(5)Mapreduce程序完成wordcount
  10. wamp 下的mysql密码_wamp下更改mysql密码
  11. stats | 线性回归(二)——模型假设和模型估计
  12. RabbitMQ之安装windows
  13. 导出qq群成员信息,并找出谁没进群或谁没改昵称
  14. matlab幂级数展开的收敛区间,常见函数的幂级数展开式收敛区间的快速确定法.pdf...
  15. get请求400错误 vue_VUE 配置proxy代理后,前台报错400 bad request
  16. 股票交易接口api的协议
  17. Mongodb之Chunk研究
  18. 用C语言将中文文本和英文文本合并为一段中文一段英文(翻译排版)
  19. Go语言核心之美 1.5-作用域
  20. Python 魔法方法详解

热门文章

  1. 不同长度数据项的排序
  2. 全国计算机等级考试题库二级C操作题100套(第82套)
  3. MySQL:union all与union区别详解
  4. 服务提供者和服务消费者
  5. Idea中Terminal中git基本操作
  6. 学习笔记~~~~~python基础
  7. Linux远程管理协议相关知识介绍
  8. Visual Studio Code 开发 .NET Core 看这篇就够了
  9. C#开发模式——单例模式
  10. vb treeview 展开子节点_C# / VB.NET 在PPT中创建、编辑PPT SmartArt图形