第七章 实现炫酷效果—图像和动画(1)

来源:互联网 发布:删除表多个字段sql 编辑:程序博客网 时间:2024/05/12 01:02

第七章实现炫酷效果—图像和动画

学完上一章,相信读者对Android画图核心部分有了一定的了解。为了实现更加炫酷的效果,我们可能会在我们的应用中使用大量的图像和动画效果。

本章我们将详细介绍Android中的各种图像对象的使用,以及动画的使用。学习完本章,相信读者可以独立开发出有着绚丽的视觉效果的Android应用了。

7.1 Android的几种常用图像类型

Android中的图像对象,主要有android.graphics.Bitmap(位图)、android.graphics.drawable.Drawable(基于Drawable类扩展出各种绘图的类)和android.graphics.drawable.Picture。

下面简单介绍一下这几种图像类型,以便对之有个大概的了解。。

1)Bitmap

称作位图,一般位图的文件格式后缀为bmp,当然编码器也有很多,如RGB565、RGB8888等等。作为一种逐像素的显示对象执行效率高,但是缺点也很明显,那就是存储效率低。我们将Bitmap理解成为一种存储对象比较好。

2)Drawable

作为Android中通用的图形对象,它可以装载常用格式的图像,比如GIF、PNG、JPG,当然也支持BMP,当然它还提供一些高级的可视化对象,比如渐变、图形等。

3)Picture

相对于Drawable和Bitmap而言,Picture对象就小巧的多,它并不存储实际的像素,仅仅记录了绘制的过程。

下面会对几种图像类型做详细的讲解。

7.2 图片的基础—Bitmap(位图)

7.2.1如何获取位图资源

前面我们大概了解了几种图像类的功能,这其中,Bitmap类是一个使用率较高的类。下面详细说明下Bitmap这个类。

先来看看如何获取位图资源。Bitmap对象没有公有的构造方法,所以不能直接创建,只能通过BitmapFactory的几个静态方法创建。

一般的,获取位图资源有以下几种方式:

1)图片放在sd卡中

Bitmap imageBitmap = BitmapFactory.decodeFile(path);

 

这里path是图片的路径,根目录是/sdcard。

2)图片在项目的res文件夹下面

ApplicationInfo appInfo = getApplicationInfo();

int resID = getResources().getIdentifier(name, "drawablePath", appInfo.packageName);

Bitmap mBitmap = BitmapFactory.decodeResource(getResources(), resID);

 

这里是通过图片的id,或直接通过R文件来获取(例如R.drawable.bitmapName)图片的。

这里的name,是该图片的名字;drawablePath是该图片存放的目录,appInfo.packageName是应用程序的包。

3)图片放在src目录下

// 图片存放的路径

String path = "com/xiangmu/test.png";

// 得到图片流

InputStream is = getClassLoader().getResourceAsStream(path);

Bitmap mBitmap = BitmapFactory.decodeStream(is);

 

4)android中有个Assets目录,这里可以存放只读文件

// 图片存放的路径为assets/test.png

String path = "test.png";

InputStream is = getResources().getAssets().open(path);

Bitmap mBitmap = BitmapFactory.decodeStream(is);

 

经验分享:

一些低版本的Android系统(2.2版本以前)对res/raw和assets文件夹资源大小有限制的,原始文件大小超过1M,将不能从APK中读出。如果你使用AssetManager 或 Resources类的方法来获取InputStream,将抛出java.io.IOException的异常。这一点是特别需要注意的。

所以,为了兼容低版本的Android系统,如果需要放入大于1M的原始文件,可以事先将大文件分割成小文件,然后在程序启动时将文件合并,拷贝到SD卡中,以供程序读取。

 

7.2.2如果获取位图的信息

很多场合,我们需要获取位图信息,比如位图大小、是否包含透明度、颜色格式等。Bitmap类中支持很多方法,下面简单介绍一些常用的方法,如表7-1所示。

方法

返回值

说明

getWidth()

int

获取位图的宽

getHeight()

int

获取位图的高

hasAlpha()

boolean

是否包含透明度

getConfig()

Config

获取颜色格式

表7-1 Bitmap类中常用的一些方法

 

经验分享:

通过方法getConfig()得到的是这个位图的颜色格式(android.graphics.Bitmap.Config),了解这个类对Android开发过程还是挺有用的。这是Bitmap的一个内部类。

public enum Config {

ALPHA_8 (2),//表示图形单个像素点由一个字节(8位)来表示,代表8位Alpha位图。

RGB_565 (4),// 5+6+5=16,表示图形单个像素点由两个字节来表示的16位RGB位图。

ARGB_4444 (5),// 4+4+4+4=16,表示图形单个像素点由两个字节来表示的16位ARGB位图。

ARGB_8888 (6);// 8+8+8+8=32,表示图形单个像素点由四个字节来表示的32位ARGB位图。

}

ALPHA_8,ARGB_4444,ARGB_8888都是透明的位图。也就是说字母A代表透明。位图位数越高代表其可以存储的颜色信息越多,当然图像也就越逼真。

 

7.2.3 位图的显示与变换

有了位图,我们就要将它显示出来。显示需要使用核心类Canvas,可以直接通过Canvas类的drawBitmap()显示位图,或者借助于BitmapDrawable来将Bitmap绘制到Canvas。具体的可以参考前面Canvas相关的章节。

位图的变换,还是要用到前面提到的类android.graphics.Matrix。变换可以在画的时候,也可以在加载图片的时候对,原图片进行变换。

在Canvas画的时候进行变换的方法如下:

drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint);

// 指定Matrix绘制位图

drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint)

 

这里主要介绍下在原有位图的基础上,缩放原位图,创建一个新的位图。下面是android.graphics.Bitmap自带的一个方法。

Bitmap.createBitmap (Bitmap source, int x, int y, int width, int height, Matrix m, boolean filter)

 

还有一种创建新位图的方法是通过BitmapFactory.decodeFile()方法。在操作Android图片的时候,我们会经常遇到内存溢出的问题,比如加载8M以上的图片的时候,很容易造成内存溢出,因为android规定一个应用可以使用的内存为8M左右,如何优化我们会在后面单独的一章节来介绍。下面我们来看看如何将一个大图变小,来给我们使用:

BitmapFactory.Options opts = new BitmapFactory.Options();

opts.inJustDecodeBounds = true;

// 这里是整个方法的关键,inJustDecodeBounds设为true时将不为图片分配内存。

BitmapFactory.decodeFile("/sdcard/image.jpg",opts);

// 获取图片的原始宽度

int srcWidth = opts.outWidth;

// 获取图片原始高度

int srcHeight = opts.outHeight;

int destWidth = 0;

int destHeight = 0;

// 缩放的比例

double ratio = 0.0;

// 按比例计算缩放后的图片大小,maxLength是长或宽允许的最大长度

if(srcWidth >srcHeight) {

ratio = srcWidth / maxLength;

destWidth = maxLength;

destHeight = (int) (srcHeight / ratio);

}else {

ratio = srcHeight / maxLength;

destHeight = maxLength;

destWidth = (int) (srcWidth / ratio);

}

BitmapFactory.Options newOpts = new BitmapFactory.Options();

// 缩放的比例,缩放是很难按准备的比例进行缩放的,目前我只发现只能通过inSampleSize来进行缩放,其值表明缩放的倍数,SDK中建议其值是2的指数值

newOpts.inSampleSize = (int) ratio + 1;

// inJustDecodeBounds设为false表示把图片读进内存中

newOpts.inJustDecodeBounds = false;

// 设置大小,这个一般是不准确的,是以inSampleSize的为准,但是如果不设置却不能缩放

newOpts.outHeight = destHeight;

newOpts.outWidth = destWidth;

// 获取缩放后图片

Bitmap destBm = BitmapFactory.decodeFile("/sdcard/ image.jpg",newOpts);

 

经验分享:

对于BitmapFactory.Options. inJustDecodeBounds说明一下。

如果该值设为true,使用BitmapFactory.decodeFile()方法将不返回实际的bitmap同时不会给其分配内存空间而返回的Options里面只包括一些解码边界信息即图片大小信息。

那么相应的方法也就出来了,通过设置inJustDecodeBounds为true,获取到outHeight(图片原始高度)和outWidth(图片的原始宽度),然后计算一个inSampleSize(缩放值),然后就可以读取图片了,这里要注意的是Options.inSampleSize 不可以小于0。也就是说先将Options的属性inJustDecodeBounds设为true,先获取图片的基本大小信息数据(信息没有保存在bitmap里面,而是保存在options里面),通过options.outHeight和options. outWidth获取的大小信息以及自己想要到得图片大小计算出来缩放比例inSampleSize,然后紧接着将inJustDecodeBounds设为false,就可以根据已经得到的缩放比例得到缩放后的图了。设置新的Options,一定要设置outHeight和outWidth如果不设置将不能缩放。

1 0
原创粉丝点击