文章出处:http://www.linuxgraphics.cn/animation/android_tween_animation.html
作者: 刘鹏
日期: 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 中实现动画
从逻辑上讲,实现动画需要如下几步:
- view 创建动画对象,设置动画属性,调用 invalidate 刷新屏幕,启动动画;
- invalidate 方法触发了 onDraw 函数;
- 在 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);
}
}
SeeAlso
<!-- Page published by Emacs Muse ends here -->
分享到:
相关推荐
本篇文章将深入探讨Android中的Fragment切换动画及其实现方法。 首先,理解Fragment的基本操作是必要的。在Android中,我们可以使用`FragmentManager`和`FragmentTransaction`来管理Fragment的生命周期和状态。例如...
8. **毕业论文参考**:对于学习Android开发的学生,这个项目可以作为毕业论文的实践部分,研究不同动画的实现原理,分析其性能差异,并提出改进方案。 9. **完整项目实践**:这个项目作为一个完整的Android应用,...
通过以上步骤,你可以为Android中的Fragment创建出丰富多彩的动画切换效果,为用户提供更加生动和交互性的体验。在实际项目中,可以根据需求调整动画细节,如动画持续时间、延迟、缩放比例等,以满足特定的设计要求...
本文档将详细介绍Android中的动画效果,并深入探讨两种主要的动画模式:渐变动画(Tweened Animation)与画面转换动画(Frame-by-Frame Animation),以及如何在XML文件中定义这些动画。 #### 二、Android动画类型 ...
在Android中,动画主要通过`Animation`类或者`Animator`类来实现。`Animation`类主要用于帧动画,而`Animator`类则用于属性动画,可以对对象的属性进行连续变化,提供了更丰富的动画效果。在这个心率项目中,可能...
《Android典型技术模块开发详解》这本书是为初入Android开发领域的工作者量身打造的指南,旨在帮助读者深入理解和掌握Android各个关键模块的开发技术。在本文中,我们将详细探讨书中可能涉及的重要知识点,并尽可能...
3. **UI组件**:在Android中,可以使用`RecyclerView`展示购物车中的商品列表。每个列表项是一个自定义的`ViewHolder`,包含了商品的图片、名称、价格等信息。当用户点击“添加”或“删除”按钮时,应调用购物车服务...
本文将围绕给定的文件信息,深入探讨Android中的动画、界面切换效果、3D效果、以及一些实用的功能模块,如读取SD卡文件等。 #### Activity 页面切换效果 在Android系统中,Activity之间的切换可以通过多种方式进行...
在提供的`CustomView_Youku`文件中,可能包含了实现这一功能的源代码示例,你可以通过学习和分析这个代码,更深入地理解Android旋转动画的实现细节。通过这样的实践,你将能够熟练地为自己的应用添加各种动态效果,...
在Android应用开发中,开发者经常会遇到各种典型的技术模块。这些模块是构建复杂应用程序的基础,涵盖了用户界面、数据管理、网络通信、多线程等多个方面。本篇将详细讲解这些核心模块,并结合提供的下载代码进行...
- Android中的动画分为两种:视图动画(View Animation)和属性动画(Property Animation)。在这个项目中,可能涉及到了这两种动画。 - 视图动画主要改变视图的视觉表现,不改变视图的实际状态,例如Alpha、...
在Android系统启动过程中,BootAnimation.cpp负责解析并播放开机动画。它可能包括读取动画帧、同步显示帧率以及处理与硬件交互的相关功能。 2. **audioplay.cpp**: 该文件很可能处理开机动画过程中的音频播放。在...
在Android中,我们可以使用`ObjectAnimator`、`ValueAnimator`或`ViewPropertyAnimator`等类来操纵视图对象的属性,创建出流畅的动画过渡;而在iOS中,我们可以利用`CALayer`的动画属性,如`transform`和`opacity`来...
1.使用google的bootanimation,不支持开机铃声2.所以修改为使用mtkbootanimation,但基线代码会报错,此资源完美解决编译报错问题,并解决首次开机无铃声的问题。
本文将深入探讨如何在Android中实现“高仿美团外卖底部按钮顶起动画”的自定义功能,该技术可以广泛应用于各种项目,提供高度的适配性和灵活性。 首先,我们关注的是“按钮顶起动画”。这种动画效果通常用于底部...
1. **帧动画(AnimationDrawable)**:在Android中,帧动画是最简单的一种动画形式,通过在指定时间间隔内连续显示一系列图片来实现动画效果。但帧动画通常不适用于复杂的、连续的图形变化,比如波浪的动态起伏。 2. ...
本项目是关于如何在Android应用中自定义一个带有动画效果的饼图组件。以下将详细介绍实现这一功能所需的关键知识点。 1. **自定义View** 自定义饼图首先需要创建一个新的`View`类,继承自Android的`View`或`...
在Android中,界面通常由XML布局文件定义,通过Java或Kotlin代码动态加载和控制。在这个游戏中,界面可能包含了游戏主屏幕、游戏设置、得分显示、游戏暂停/恢复界面等。开发者可能使用了`ConstraintLayout`、`...
在Android开发中,模仿知名应用的用户界面和交互体验是一种常见的学习和提升技术的方式。"Android仿微信6.0,可自定义切换动画"这个项目就是针对微信6.0版本的UI设计进行的一次实现,它允许开发者创建类似微信的应用...
同时,可以使用`Platform`模块根据不同的操作系统(iOS或Android)应用不同的样式。 5. **平台兼容性**:React Native的一个强大特性是跨平台兼容性。开发者可以编写一次代码,然后在iOS和Android上运行。但需要...