学习Android 有一段时间了,看完了Android SDK 中的大部 分文档,但是始终感觉自己还缺少很多,后来发现,Android SDK中只是介绍了google 自 己开发的那一部分如何使用,Android中引用至Java 的部分 如何使用却没有说明。当然这也不是Google的职 责,但是这对我们C++程序员来说的确是缺少了很多,在这里我们将对Google“缺少的部分”并结合Android SDK中Reference说明来详细介绍,并不断的补充完善。
Android画图学习 总结(一)——类的简介
首先,如何获取 res 中的资源
数据包package:android.content.res
主要 类:Resources
Android SDK中的简介:Class for accessing an application’s resources.Class for accessing an application’s resources. This sits on top of the asset manager of the application (accessible through getAssets()) and provides a higher-level API for getting typed data from the assets.
其主要接口按照功能,划分为以下三部分:
getXXXX()
例如:
int getColor(int id)
Drawable getDrawable(int id)
String getString(int id)
直接获取res中存放的资源
InputStream openRawResource(int id)
获取资源的数据流,读取资源数据
void parseBundleExtras(
XmlResourceParser parser, Bundle outBundle) 从XML文件中获取数据
Resource为每种资源提供了相应的接口来获取这种资源,除了可以直接获取资源外,还额外提供了以数据流的 方式获取资源,这在以后的应用程序 开发中 会经常使用,那么如何获取Resources了,如下:Resources r = this.getContext().getResources();
其次,如何获取资源中的画图对象
数据包 package:android.graphics.drawable
主要类:Drawable
Android SDK中的简介:A Drawable is a general abstraction for “something that can be drawn.” Most often you will deal with Drawable as the type of resource retrieved for drawing things to the screen; the Drawable class provides a generic API for dealing with an underlying visual resource that may take a variety of forms.
看了以上简介,发现Drawable是个virtual class,具体如何画图,需要具体分析Drawable的子类,例如:BitmapDrawable
Android SDK中的简介:A Drawable that wraps a bitmap and can be tiled, stretched, or aligned. You can create a BitmapDrawable from a file path, an input stream, through XML inflation, or from a Bitmap object. It can be defined in an XML file with the <bitmap> element.
其主要接口如下:
BitmapDrawable()
BitmapDrawable(Bitmap bitmap)
BitmapDrawable(String filepath)
BitmapDrawable(InputStream is)
void draw(Canvas canvas)
Draw in its bounds (set via setBounds) respecting optional effects such as alpha (set via setAlpha) and color filter (set via setColorFilter).
final Bitmap getBitmap()
final Paint getPaint()
Drawable是个抽象类,在 BitmapDrawable中我们就看到位图的具体操作,在仔细看下BitmapDrawable的构造函数,我们就会发现与Resource中的 openRawResource()接口是相对应的,就可以通过以下方法来获取位图:
Resources r = this.getContext().getResources();
Inputstream is = r.openRawResource(R.drawable.my_background_image);
BitmapDrawable bmpDraw = new BitmapDrawable(is);
Bitmap bmp = bmpDraw.getBitmap();
关 于Drawable深入的学习与理解,请阅读Android画图学习总结(三)——Drawable
然后,看几个常用的辅助类
1. Paint
数据包package:android.graphics
Android SDK中的简介:The Paint class holds the style and color information about how to draw geometries, text and bitmaps. 主要就是定义:画刷的样式,画笔的大小/颜色等。
2. Typeface
数据包 package:android.graphics
Android SDK中的简介:The Typeface class specifies the typeface and intrinsic style of a font. 主要就是定义:字体。
最后,核心类显示资源
数据包 package:android.graphics
主要类:Canvas
Android SDK中的简介:The Canvas class holds the “draw” calls. To draw something, you need 4 BASIC components: A Bitmap to hold the pixels, a Canvas to host the draw calls (writing into the bitmap), a drawing primitive (e.g. Rect, Path, text, Bitmap), and a paint (to describe the colors and styles for the drawing).
按照结构的功能,将主要接口分为以下3部分:
boolean clipXXXX() Region区域操作:
DIFFERENCE
INTERSECT
REPLACE
REVERSE_DIFFERENCE
UNION
XOR
void drawXXXX() 画图函数
void rotate()
void scale()
void skew()
void translate() 画布操作函数
Region在这里需要特殊说明下:Region就是一个区域,也就是画布(Canvas)中 的有效区域,在无效区域上draw,对画布没有任何改变。
总结说明
在写代码前,必须先仔细看下这几个主要的类,在这里我也只 是把SDK中的介绍稍微总结下,它代替不了你对SDK的详细阅读,毕竟SDK是最详细的说明文档,在后续篇幅中再深入详细的介绍。
Android画图学习 总结(二)——Bitmap
通 过前一篇的 学习,对Android 画图核心部分有了一定的了解,后面篇幅,我们将详细介绍Android中的各种画图对象的使用,首先介绍我们最常用的Bitmap(位图)。位图是我们开 发中最常用的资源,毕竟一个漂亮的界面对用户是最有吸引力的。按照对位图的操作,分为以下几个功能分别介绍:
1. 从资源中获取位图
2. 获取位图的信息
3. 显示位图
4. 位图缩放
5. 位图旋转
1. 从资源中获取位图
在前一篇幅介绍了:先获取Resource,然后可以通过资源ID获取Drawable,也可以通过资源ID获取资 源文件的数据流。使用第一种方法 比较容易,下面详细说明第二种方法。通过Resource的函数:InputStream openRawResource(int id)获取得到资源文件的数据流后,也可以通过2种方法来获取Bitmap,如下:
使用 BitmapDrawable
(A Drawable that wraps a bitmap and can be tiled, stretched, or aligned.)
1. 使用BitmapDrawable (InputStream is)构造一个BitmapDrawable;
2. 使用BitmapDrawable类的getBitmap()获取得到位图;
BitmapDrawable 也提供了显示位图等操作
使用BitmapFactory
(Creates Bitmap objects from various sources, including files, streams, and byte-arrays.)
1. 使用BitmapFactory类decodeStream(InputStream is)解码位图资源,获取位图
BitmapFactory 的所有函数都是static,这个辅助类可以通过资源ID、路径、文件、数据流等方式来获取位图。
以上方法在编程的时候可以自由选择, 在Android SDK 中 说明可以支持的图片格式如下:png (preferred), jpg (acceptable), gif (discouraged),虽然bmp格式没有明确说明,但是在Android SDK Support Media Format中是明确说明了。
2. 获取位图的信息
要获取位图信息,比如位图大小、是否包含透明度、颜色格式等,获取得到Bitmap就迎刃而解了,这些信息在 Bitmap的函数中可以轻松获取到。 Android SDK中对Bitmap有详细说明,阅读起来也比较容易,不在此详细说明,这里只是辅助说明以下2点:
* 在Bitmap中对RGB颜色格式使用Bitmap.Config定义,仅包括ALPHA_8、ARGB_4444、 ARGB_8888、RGB_565,缺少了一些其他的,比如说RGB_555,在开发中可能需要注意这个小问题;
* Bitmap还提供了compress()接口来压缩图片,不过AndroidSAK只支持PNG、JPG格式的压缩;其他格式的需要 Android开发人员自己补充了。
3. 显示位图
显示位图需要使用核心类Canvas,可以直接通过Canvas 类的drawBirmap()显示位图,或者借助于BitmapDrawable来 将Bitmap绘制到Canvas。具体如何显示位图不是主要的问题,主要问题是如何获取Canvas,参考Snake中的方法,做了个简单的例子 testView,提供给大家下载。
testView例子介绍:其包含2个类 testActivity,testView;testActivity继承与 Activity,testView继承与View。这个例子就是将testView直接作为testActivity的窗口,这样我们就可以直接在 testView画图了。具体如何实现的,请大家参考testActivity的onCreate()中的代码,以及layout/main.xml中的 设置。在testView的onDraw()直接画图,结果在例子程序运行后就可以直接在界面上显示了。
4. 位图缩放
位 图的缩放,在Android SDK中提供了2种方法:
* 将一个位图按照需求重画一遍,画后的位图就是我们需要的了,与位图的显示几乎一样:
drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint)
* 在原有位图的基础上,缩放原位图,创建一个新的位图:
createBitmap(Bitmap source, int x, int y, int width, int height, Matrix m, boolean filter)
第2种方法一看就 明白,对于第一种方法,举个简单的例子来说明:
int w = 320,h = 240;
String mstrTitle = “感受Android带给我们的新体验”;
Bitmap mbmpTest = Bitmap.createBitmap(w,h, Config.ARGB_8888);
Canvas canvasTemp = new Canvas(mbmpTest);
canvasTemp.drawColor(Color.WHITE);
Paint p = new Paint();
String familyName = “宋体”;
Typeface font = Typeface.create(familyName,Typeface.BOLD);
p.setColor(Color.RED);
p.setTypeface(font);
p.setTextSize(22);
canvasTemp.drawText(mstrTitle,0,100,p);
显 示位图mbmpTest,就会发现一张320×240、白色背景、红色“宋体”文字的图片,如下:
这 个例子没有位图缩放的任何操作?的确,但是这是我在想如何写个简单的位图缩放的小程序时,最先想到的。看完这个例子,我想你就应该明白如何实现位图的缩 放了。不要小瞧了这个例子,虽然与位图缩放关系不大,但是却可以让你理解位图缩放的本质:将原始位图按照需求显示出来,就创造了一张新的位图。
5. 位图旋转
位图的旋转,离不开Matrix。Matrix在线性代数中都学习过,Android SDK提供了Matrix类,可以通过各种接口来设置矩阵。结合上面的例子程序,将位图缩放例子程序在显示位图的时候前,增加位图旋转功能,修改代码如 下:
Matrix matrix = new Matrix();
//matrix.postScale(0.5f, 0.5f);
matrix.setRotate(90,120,130);
canvas.drawBitmap(mbmpTest, matrix, mPaint);
旋转后的位图显示如下:
Bitmap-Matrix
除 了这种方法之外,我们也可以在使用Bitmap提供的函数如下:
public static Bitmap createBitmap (Bitmap source, int x, int y, int width, int height, Matrix m, boolean filter),在原有位图旋转的基础上,创建新位图。
总结说明
对位图的操作,结合Android SDK中的类,详细的介绍完了。最后还需要强调的是:这篇文章只是对Android SDK中代码阅读分析,它代替不了你阅读Android SDK,深入的学习还是要仔细的阅读Android SDK。
Android画图学习 总结(三)——Drawable
public class testView extends View {
private ShapeDrawable mDrawable;
public testView(Context context) {
super(context);
int x = 10;
int y = 10;
int width = 300;
int height = 50;
mDrawable = new ShapeDrawable(new OvalShape());
mDrawable.getPaint().setColor(0xff74AC23);
mDrawable.setBounds(x, y, x + width, y + height);
}
protected void onDraw(Canvas canvas)
super.onDraw(canvas);
canvas.drawColor(Color.WHITE);//画白 色背景
mDrawable.draw(canvas);
}
}
程序的运行结果,显示如下:
![](https://i-blog.csdnimg.cn/blog_migrate/71befa5117242bc321969d8da58a4b44.png)
简 要解析:
1. 创建一个OvalShape(一个椭圆);
2. 使用刚创建的OvalShape构造一个ShapeDrawable对象mDrawable
3. 设置mDrawable的颜色;
4. 设置mDrawable的大小;
5. 将mDrawable画在testView 的画布上;
这个简单的例子 可以帮我们理解什么是Drawable,Drawable就是一个可画的对象,其可能是一张位图(BitmapDrawable), 也可能是一个图形(ShapeDrawable),还有可能是一个图层(LayerDrawable),我们根据画图的需求,创建相应的可画对象,就可以 将这个可画对象当作一块“画布(Canvas)”,在其上面操作可画对象,并最终将这种可画对象显示在画布上,有点类似于“内存画布“。
上 面只是一个简单的使用Drawable的例子,完全没有体现出Drawable的强大功能。Android SDK中说明了Drawable主要的作用是:在XML中定义各种动画,然后把 XML当作Drawable资源来读取,通过Drawable显示动画。下面举个使用TransitionDrawable 的例子,创建一个Android工程,然后再这个工程的基础上修改,修改过程如下:
1、去掉layout/main.xml中的 TextView,增加ImagView,如下:
<ImageView
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:tint=”#55ff0000″
android:src=”@drawable/my_image”/>
2、 创建一个XML文件,命名为expand_collapse.xml,内容如下:
<?xml version=”1.0″ encoding=”UTF-8″?>
<transition xmlns:android=”http://schemas.android.com/apk/res/android”>
<item android:drawable=”@drawable/image_expand”/>
<item android:drawable=”@drawable/image_collapse”/>
</transition>
需 要3张png图片,存放到res/drawable目录下,3张图片分别命名为:my_image.png、image_expand.png、 image_collapse.png。
3、修改Activity中的代码,内容如下:
LinearLayout mLinearLayout;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mLinearLayout = new LinearLayout(this);
ImageView i = new ImageView(this);
i.setAdjustViewBounds(true);
i.setLayoutParams(new Gallery.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
mLinearLayout.addView(i);
setContentView(mLinearLayout);
Resources res = getResources();
TransitionDrawable transition =
(TransitionDrawable) res.getDrawable(R.drawable.expand_collapse);
i.setImageDrawable(transition);
transition.startTransition(10000);
}
4、 如果修改的没有错误,运行程序,结果显示如下:
初始图片
TransitionDrawable-begin
![](https://i-blog.csdnimg.cn/blog_migrate/adaf3810e330b14fc7b4bcacec8044d2.png)
过 渡中的图片
TransitionDrawable-mid
![](https://i-blog.csdnimg.cn/blog_migrate/8143c3e9dee3b8f342d26107e3ef11b7.png)
最 后的图片
TransitionDrawable-end
![](https://i-blog.csdnimg.cn/blog_migrate/e4c3b7e8bfd17763c5086f6cfde85ab7.png)
屏 幕上动画显示的是: 从图片image_expand.png过渡到image_collapse.png,也就是我们在expand_collapse.xml中定义的一个 transition动画。看完这个例子,你对Drawable的理解是否又深入些?这里提供这个程序的源代码,供大家下载,可以在这个例子的基础上去体 会其他的Drawable,来加深对Drawable的理解。
总结说明
通过以上2个例子程序,相信对Drawable会有一 定的认识了,在以后的篇幅中会介绍更多的例子,更加深入的学习和理解Drawable。具体还有哪些Drawable,大家到Android SDK去深入学习吧。
代码实例
xml代码:main.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<com.test.testview
android:id="@+id/testView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
tileSize="12"/>
</FrameLayout>
testview.Java 代码 如下:
package com.test;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.graphics.Bitmap.Config;
import android.util.AttributeSet;
import android.view.View;
public class testview extends View{
private Bitmap mbmpTest=null;
private final Paint mPaint = new Paint();
private final String mstrTitle="android Drawable 实例";
public testview(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public testview(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
mPaint.setColor(Color.GREEN);
}
public testview(Context context, AttributeSet attrs)
{
super(context, attrs);
mPaint.setColor(Color.GREEN);
}
public boolean initBitmap(int w,int h,int c)
{
mbmpTest = Bitmap.createBitmap(w,h, Config.ARGB_8888);
Canvas canvas = new Canvas(mbmpTest);
canvas.drawColor(Color.WHITE);
Paint p = new Paint();
String familyName = "����";
Typeface font = Typeface.create(familyName,Typeface.BOLD);
p.setColor(Color.RED);
p.setTypeface(font);
p.setTextSize(22);
canvas.drawText(mstrTitle,0,100,p);
return true;
}
@Override
public void onDraw(Canvas canvas)
{
super.onDraw(canvas);
/*if(mbmpTest!=null)
{
Rect rtSource = new Rect(0,0,320,240);
Rect rtDst = new Rect(0,0,320,240);
canvas.drawBitmap(mbmpTest, rtSource,rtDst, mPaint);
}*/
if(mbmpTest!=null)
{
Matrix matrix = new Matrix();
//matrix.postScale(0.5f, 0.5f);
matrix.setRotate(90,120,120);
canvas.drawBitmap(mbmpTest, matrix, mPaint);
}
}
}
testActivity.java代码如下:
package com.test;
import android.app.Activity;
import android.os.Bundle;
public class testActivity extends Activity {
private testview mTestview;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mTestview = (testview) findViewById(R.id.testView);
mTestview.initBitmap(320,240,0xcccccc);
}
}
显 示结果:
![点击查看原始大小图片](https://i-blog.csdnimg.cn/blog_migrate/61844136178f30adbb37513e0f6c94b2.png)
Android画图学习 总结(四)——Animation(上)
随 着对Drewable的深入了解,发现了Drawable更加强大的功能:显示Animation。Android SDK 介 绍了2种Animation:
* Tween Animation:通过对场景里的对象不断做图像变换(平移、缩放、旋转)产生动画效果
* Frame Animation:顺序播放事先做好的图像,跟电影类似
在使用Animation前,我们先学习如何定义 Animation,这对我们使用Animation会有很大的帮助。Animation是以XML格式 定义的,定义好的XML文件存放在res/anim中。由于Tween Animation与Frame Animation的定义、使用都有很大的差异,我们将分开介绍,本篇幅中介绍Tween Animation的定义与使用,后续篇幅再详细介绍Frame Animation。按照XML文档的结构【父节点,子节点,属性】来介绍Tween Animation,其由4种类型:
* Alpha:渐变透明度动画效果
* Scale:渐变尺寸伸缩动画效果
* Translate:画面转换位置移动动画效果
* Rotate:画面转换位置移动动画效果
在介绍以上4种类型前,先介绍Tween Animation共同的节点属性,关于节点的命名原则,请阅读AndroidManifest.xml 文件结构说明。
表一
属 性[类型] 功能
Duration[long] 属性为动画持续时间 时间以毫秒为单位
fillAfter [boolean] 当设置为true ,该动画转化在动画结束后被应用
fillBefore[boolean] 当设置为true ,该动画转化在动画开始前被应用
interpolator
指定一个动画的插入器 有一些常见的插入器
accelerate_decelerate_interpolator
加 速-减速 动画插入器
accelerate_interpolator
加速-动画插入器
decelerate_interpolator
减 速- 动画插入器
其他的属于特定的动画效果
repeatCount[int] 动画的重复次数
RepeatMode[int] 定义重复的行为 1:重新开始 2:plays backward
startOffset[long] 动画之间的时间间隔,从上次动画停多少时间开始执行下个动画
zAdjustment[int] 定义动画的Z Order的改变 0:保持Z Order不变
1:保持在最上层
-1:保持在最下层
看了以上节点,大家是不是都想开始定义动画了。下面我们就开始 结合具体的例子,介绍4种类型各自特有的节点元素。
表二
XML节点 功能说明
alpha 渐变透明度动画效果
<alpha
android:fromAlpha=”0.1″
android:toAlpha=”1.0″
android:duration=”3000″ />
fromAlpha
属性为动画起始时透明度
0.0表示完全透明
1.0表示完全不透明
以 上值取0.0-1.0之间的float数据类型的数字
toAlpha 属性为动画结束时透明度
表三
scale 渐变尺寸伸缩动画效果
<scale
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:fromXScale="0.0"
android:toXScale="1.4"
android:fromYScale="0.0"
android:toYScale="1.4"
android:pivotX="50%"
android:pivotY="50%"
android:fillAfter="false"
android:startOffset="700"
android:duration="7000"
android:repeatCount="1"
/>
fromXScale[float] fromYScale[float] 为动画起始时,X、Y坐标上的伸缩尺寸 0.0表示收缩到没有
1.0表示正常无伸缩
值小于 1.0表示收缩
值大于1.0表示放大
toXScale [float]
toYScale[float] 为动画结束时,X、Y坐标上的伸缩尺寸
pivotX[float]
pivotY[float] 为动画相对于物件的X、Y坐标的开始位置 属性值说明:从0%-100%中取值,50%为物件的X或Y方向坐标上的中点位置
表 四
translate 画面转换位置移动动画效果
<translate
android:fromXDelta="0"
android:toXDelta="-80"
android:fromYDelta="-60"
android:toYDelta="300"
android:duration="2000"
/>
fromXDelta
toXDelta 为动画、结束起始时 X坐标上的位置
fromYDelta
toYDelta 为动画、结束起始时 Y坐标上的位置
表 五
rotate 画面转移旋转动画效果
<rotate
android:interpolator=”@android:anim/accelerate_decelerate_interpolator”
android:fromDegrees=”0″
android:toDegrees=”+350″
android:pivotX=”50%”
android:pivotY=”50%”
android:duration=”3000″ />
fromDegrees 为动画起始时物件的角度 说明
当角度为负数——表示逆时针旋转
当角度为正数——表示 顺时针旋转
(负数from——to正数:顺时针旋转)
(负数from——to负数:逆时针旋转)
(正数from——to正 数:顺时针旋转)
(正数from——to负数:逆时针旋转)
toDegrees 属性为动画结束时物件旋转的角度 可以大于360度
pivotX
pivotY 为动画相对于物件的X、Y坐标的开始位 说明:以上两个属性值 从0%-100%中取值
50%为物件的X或Y方向坐标上的中点位置
看了上面的例子,想必大家也想看下,这些定义的动 画,运行起来是什么样效果,下面运行Scale例子中的动画,界面变化如下:
按 照上面的讲述学习完了Tween Animation的定义,对Tween Animation有了详细的了解,再去了解下Android SDK的animation package(android.view.animation),其提供了操作Tween Animation所有的类。
Android SDK提供了基类:Animation,包含大量的set/getXXXX()函数来设置、读取Animation的属性,也就是前面表一中显示的各种属 性。Tween Animation由4种类型:alpha、scale、translate、roate,在Android SDK中提供了相应的类,Animation类派生出了AlphaAnimation、ScaleAnimation、 TranslateAnimation、RotateAnimation分别实现了平移、旋转、改变 Alpha 值等动画,每个子类都在父类的基础上增加了各自独有的属性。再去看下这几个类的构造函数,是不是与我们在表二、表三、表四、表五种定义的属性完全一样。
在 了解了Tween Animation的定义,对android.view.animation有了一些基本的认识后,开始介绍Tween Animation如何使用。Android SDK提供了2种方法:直接从XML资源中读取Animation,使用Animation子类的构造函数来初始化Animation对象,第二种方法在 看了Android SDK中各个类的说明就知道如何使用了,下面简要说明从XML资源中读取Animation,按照应用程序 开发的 过程,介绍整个使用的过程,如下:
* 创建Android工程;
* 导入一张图片资源;
* 将res/layout/main.xml中的TextView取代为ImageView;
* 在res下创建新的文件夹anim,并在此文件夹下面定义Animation XML文件;
* 修改OnCreate()中的代码,显示动画资源;
关键代码,解析如下:
//main.xml中的 ImageView
ImageView spaceshipImage = (ImageView) findViewById(R.id.spaceshipImage);
//加载动画
Animation hyperspaceJumpAnimation =
AnimationUtils.loadAnimation(this, R.anim.hyperspace_jump);
//使用ImageView显示动画
spaceshipImage.startAnimation(hyperspaceJumpAnimation);
工 程的源代码提供给大家下载,下载地址,这里简要解析如下:
* AnimationUtils提供了加载动画的函数,除了函数loadAnimation(),其他的到Android SDK中去详细了解吧;
* 所谓的动画,也就是对 view 的内容做一次图形变换;
总结说明
看了这个长篇幅的介绍,详细大家对Tween Animation的定义、使用都有了比较深入的了解,由于篇幅有限,这里将Android SDK中的内容省略了不少,比如说:Interpolator,需要大家自己去Android SDK中仔细阅读。
Android画图学习 总结(四)——Animation(中)
在Android 画 图学习总结(四)——Animation(上)中详细介绍了Tween Animation的定义、使用,由于篇幅有限,很多中重要的方面没有说明,这篇文章一方面做个完整的总结说明,另外一方面补充说明上一篇幅遗漏的问题, 帮助大家更好的理解Tween Animation。
对Tween Animation的本质做个总结:Tween Animation通过对 View 的内容完成一系列的图形变换 (包括平移、缩放、旋转、改变透明度)来实现动画效果。具体来讲,预先定义一组指令,这些指令指定了图形变换的类型、触发时间、持续时间。这些指令可以是 以 XML 文件方式定义,也可以是以源代码方式定义。程序沿着时间线执行这些指令就可以实现动画效果。
在这里,我们需要对2个问题 进行深入的解析:
* 动画的运行时如何控制的?
* 动画的运行模式。
动画的运行时如何控 制的?
这个问题,我们也就也就是上一篇幅中提到的Tween Animation,估计大家对什么是Interpolator、到底有什么作用,还是一头雾水,在这里做个详细的说明。按照Android SDK 中对 interpolator的说明:interpolator定义一个动画的变化率(the rate of change)。这使得基本的动画效果(alpha, scale, translate, rotate)得以加速,减速,重复等。
用 通俗的一点的话理解就是:动画的进度使用 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。Android 提供了几个 Interpolator 子类,实现了不同的速度曲线,如下:
AccelerateDecelerateInterpolator 在动画开始与介绍的地方速率改变比较慢,在中间的时候加速
AccelerateInterpolator 在动画开始的地方速率改变比较慢,然后开始加速
CycleInterpolator 动画循环播放特定的次数,速率改变沿着正弦曲线
DecelerateInterpolator 在动画开始的地方速率改变比较慢,然后开始减速
LinearInterpolator 在动画的以均匀的速率改变
对于 LinearInterpolator ,变化率是个常数,即 f (x) = x.
public float getInterpolation(float input) {
return input;
}
Interpolator 其他的几个子类,也都是按照特定的算法,实现了对变化率。还可以定义自己的 Interpolator 子类,实现抛物线、自由落体等物理效果。
动 画的运行模式
动画的运行模式有两种:
* 独占模式,即程序主线程进入一个循环,根据动画指令不断刷新屏幕,直到动画结束;
* 中断模式,即有单独一个线程对时间计数,每隔一定的时间向主线程发通知,主线程接到通知后更新屏幕;
额外补充说 明:Transformation 类
Transformation 记录了仿射矩阵 Matrix,动画每触发一次,会对原来的矩阵做一次运算, View 的 Bitmap 与这个矩阵相乘就可实现相应的操作(旋转、平移、缩放等)。Transformation 类封装了矩阵和 alpha 值,它有两个重要的成员,一是 mMatrix,二是 mAlpha。Transformation 类图如下所示:
Transformation
总 结说明
图形变换通过仿射矩阵实现。图形变换是图形学中的基本知识,简单来说就是,每种变换都是一次矩阵运算。在 Android 中,Canvas 类中包含当前矩阵,当调用 Canvas.drawBitmap (bmp, x, y, Paint) 绘制时,A ndroid 会先把 bmp 做一次矩阵运算,然后将运算的结果显示在 Canvas 上。这样,编程人员只需不断修改 Canvas 的矩阵并刷新屏幕,View 里的对象就会不停的做图形变换,动画就形成了。
Android画图学习 总结(四)——Animation(下)
在Android 画 图学习总结(四)——Animation(上)中,我们详细介绍了Tween Aniamation,这里我们将介绍另外一种动画Frame Animation。在前面已经说过,Frame Animation是顺序播放事先做好的图像,跟电影类似。不同于animation package, Android SDK 提供了另 外一个类AnimationDrawable来定义、使用Frame Animation。
Frame Animation可以在XML Resource定义(还是存放到res/anim文件夹下),也可以使用AnimationDrawable中的API定义。由于Tween Animation与Frame Animation有着很大的不同,因此XML定义的格式也完全不一样,其格式是:首先是animation-list根节点,animation- list根节点中包含多个item子节点,每个item节点定义一帧动画:当前帧的drawable资源和当前帧持续的时间。下面对节点的元素加以说 明:
XML属性 说明
drawable 当前帧引用的drawable资源
duration 当前帧显示的时间(毫秒为单位)
oneshot 如果为true,表示动画只播放一次停止在最后一帧上,如果设置为false表示动画循环播放。
variablePadding If true, allows the drawable’s padding to change based on the current state that is selected.
visible 规定drawable的初始可见性,默认为flase;
下面就给个具 体的XML例子,来定义一帧一帧的动画:
<animation-list xmlns:android=”http://schemas.android.com/apk/res/android”
androidneshot=”true”>
<item android:drawable=”@drawable/rocket_thrust1″ android:duration=”200″ />
<item android:drawable=”@drawable/rocket_thrust2″ android:duration=”200″ />
<item android:drawable=”@drawable/rocket_thrust3″ android:duration=”200″ />
</animation-list>
上面的XML就定义了一个Frame Animation,其包含3帧动画,3帧动画中分别应用了drawable中的3张图 片:rocket_thrust1,rocket_thrust2,rocket_thrust3,每帧动画持续200毫秒。
然后我们将以上 XML保存在res/anim/文件夹下,命名为rocket_thrust.xml,显示动画的代码,如下:在OnCreate()中增加如下代码:
ImageView rocketImage = (ImageView) findViewById(R.id.rocket_image);
rocketImage.setBackgroundResource(R.anim.rocket_thrust); rocketAnimation = (AnimationDrawable) rocketImage.getBackground();
最 后还需要增加启动动画的代码:
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
rocketAnimation.start();
return true;
}
return super.onTouchEvent(event);
}
代码运行的结果想必大家 应该就知道了(3张图片按照顺序的播放一次),不过有一点需要强调的是:启动Frame Animation动画的代码rocketAnimation.start();不能在OnCreate()中,因为在OnCreate()中 AnimationDrawable还没有完全的与ImageView绑定,在OnCreate()中启动动画,就只能看到第一张图片。
下面, 阅读Android SDK中对AnimationDrawable的介绍,有个简单的了解:
AnimationDrawable
获 取、设置动画的属性
int getDuration() 获取动画的时长
int getNumberOfFrames() 获取动画的帧数
boolean isOneShot()
Void setOneShot(boolean oneshot) 获取oneshot属性
设置oneshot属性
void inflate(Resurce r,XmlPullParser p,
AttributeSet attrs)
增加、获取帧动画
Drawable getFrame(int index) 获取某帧的Drawable资源
void addFrame(Drawable frame,int duration) 为当前动画增加帧(资源,持续时长)
动画控制
void start() 开始动画
void run() 外界不能直接掉调用,使用start()替代
boolean isRunning() 当前动画是否在运行
void stop() 停止当前动画
总结说明
Frame Animation的定义、使用比较简单,在这里已经详细介绍完了,更加深入的学习还是到Android SDK去仔细了解吧,在Android SDK中也包含很多这方面的例子程序。