转载请表明出处:http://blog.csdn.net/u012637501(嵌入式_小J的天空)
为了增强用户之间的交互,Android系统中提供了一些API和部件给我们开发美观有趣的应用。比如Android系统提供了ImageView来显示静态图片、AnimationDrawble来开发逐帧动画以及通过Animation对普通图片使用不减动画等。另外,Android应用中的图片不仅包括*.png、*.jpg、*.gif等格式的位图,也包括使用XML资源文件定义的各种Drawable对象。关于Drawable对象的使用,主要有以下几个方面:
(1)@drawable/file_name:在XML资源文件中通过@drawable/file_name来访问该Drawable对象;
(2)R.drawable.file_name:在Java代码中通过该图片资源的R清单文件中的索引项R.drawable.file_name来访问该Drawable对象。
(3)Resources.getDrawable(int id):由于R.drawable.file_name是一个int类型的常量,其只代表Drawable对象的ID,如果在Java程序中需要获得实际的Drawable对象,则可调用该方法来获取。
一、图片处理API
*Bitmap:代表一张位图;
*BitmapDrawable:用于封装图片,即封装的图片就是一个Bitmap对象;
*BitmapFactory:为一个工具类,用于提供大量的方法,这些方法可用于从不同的数据源来解析、创建一个Bitmap对象。
1.Bitmap类
代表一张位图(即普通的*.png、*.jpg、*.gif等格式图片),Bitmap类负责管理和转换原始位图图形,其常用方法有:
(1)从其他途径创建一个Bitmap对象
>static Bitmap createBitmap(Bitmap source,int x,int y,int width,int height):从源位图source的 指定坐标点(给定x、y)开始,从中"挖取"宽width、高height的一块处理用于创建新的Bitmap对象。
>static Bitmap createScaledBitmap(Bitmap src,iint dstWidth,int dstHeight,boolean filter):对源位图src进行缩放,缩放成宽
dstWidth、高dstHeight的新位图。
>static Bitmap createBitmap(int width,int height,Bitmap.Config
config):创建一个宽width、高height的新位图,其中Bitmap.Config为位图的配置是Bitmap的嵌入类用于描述像素是怎样存储的(ALPHA_8、ARGB_8888 、RGB_565 )。
>static Bitmap createBitmap(Bitmap
source,int x,int y,int width,int height,Matrix m,boolean filter):从源位图source的指定坐标点(给定x、y)开始,从中"挖取"宽width、高height的一块位图来创建新的Bitmap对象,并按Matrix指定的规则进行变换。
(2)获取位图的宽度、高度大小
>final int getHeight() :返回位图的高度
>final int getWidth() :返回位图的宽度
>int getScaledHeight(int targetDensity)
:返回被缩放位图的高度
>int getScaledWidth(int targetDensity)
:返回被缩放位图的宽度
(3)判断Bitmap对象是否被收回
>final boolean isRecycled()
:返回该Bitmap对象是否已被回收
>void recycle() :强制一个Bitmap对象立即回收自己
注释:这里提到Bitmap对象的回收问题,主要是因为大部分时候,我们只要把图片放在/res/drawable-mdpi目录下,就可以在程序中通过图片对象的ID来获取封装该图片的Drawable对象。但由于手机系统的内存比较小,如果系统不停地去解析、创建Bitmap对象,可能由于前面创建Bitmap所占用的内存还没有回收而导致程序运行时引发"内存溢出"错误。
2.BitmapDrawable类
BitmapDrawable类用于包装一个位图,并且该Drawable可被平铺、拉升、对齐等操作。我们可以从一个文件路径、一个输入流、XML或者Bitmap对象来创建一个BitmapDrawable对象。
(1)构造方法
>BitmapDrawable(Bitmap
bitmap)
>BitmapDrawable(Resources
res, Bitmap bitmap)
(2)常用方法
>final
Bitmap getBitmap():获取该BitmapDrawable对象对应的Bitmap对象
>final
Paint getPaint() :获取渲染该drawable的paint对象
>void
setAlpha(int alpha) :为drawable对象指定透明度
注释:我们可以使用"BitmapDrawable drawable = new BitemapDrawable(bitmap);"语句把一个Bitmao对象包装成BitmapDrawable对象;通过"Bitmap
bitmap = drawable.getBitmap()"语句来获取BitmapDrawable所包装的Bitmap对象。
3.BitmapFactory类
BitmapFactory类 为一个工具类,提供大量的方法可用于从不同的数据源来解析、创建一个Bitmap对象。比如Android应用需要访问其他存储路径(SD卡中)里的图片,都需要借助于BitmapFactory来解析和创建一个Bitmap对象。
(1)构造方法:BitmapFactory()
(2)常用方法:
>static
Bitmap decodeByteArray(byte[] data, int offset, int length) :从指定字节数组的offset位置开始,将长度为length的字节数据解析成Bitmap对象
>static
Bitmap decodeFile(String pathName) :从pathName指定的文件中解析、创建Bitmap对象
>static
Bitmap decodeFileDescriptor(FileDescriptor fd):从FileDescriptor(文件描述符)对应的文件中解析、创建Bitmap对象
>static
Bitmap decodeResource(Resources res, int id) :根据给定的资源ID从指定资源中解析、创建Bitmap对象
>static
Bitmap decodeStream(InputStream is):从指定输入流中解析、创建Bitmap对象
二、简易图片查看器开发思路
本应用主要是实现查看/res/assets目录下所有的图片,对于图片的替换主要是调用ImageView的setImageBitmap(Bitmap
bitmap)方法。 所以,我们最终的目的就是要获得切换图片对应的Bitmap对象。具体步骤:(1)首先需要获取assets所有文件列表("AssetManager assets=getAssets();String[] assetsImages = assets.list("");然后,(2)获取并打开字符串数数组中一张图片资源输入流(InputStream
stream = assets.open(assetsImages[currentImage])
(3) 调用Bitfactory.decodeStream(InputStream stream)方法获取该位图的Bitmap对象,最后在调用ImageView的setImageBitmap(Bitmap
bitmap)方法实现切换图片效果。
注意:由于图片的切换,系统会不停地去解析、创建Bitmap对象,所以,为了避免手机内存"溢出"情况,在切换图片之前需要判定当前Bitmap是否被收回,否者需要强制收回该图片。
BitmapDrawable bitmapDrawable
= (BitmapDrawable)imageView.getDrawable(); //获取当前图片的BitmapDrawable对象
if(bitmapDrawable != null
&& !bitmapDrawable.getBitmap().isRecycled()) //通过BitmapDrawable对象获得对应的Bitmap对象及其方法
{
bitmapDrawable.getBitmap().recycle();
}
三、源码实现
实现:开发一个查看/assets/目录下图片的图片查看器。
BitmapTest.java
<span style="font-size:18px;">package com.example.bitmaptest; import java.io.IOException; import java.io.InputStream; import android.app.Activity; import android.content.res.AssetManager; import android.graphics.BitmapFactory; import android.graphics.drawable.BitmapDrawable; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.ImageView; import android.widget.Toast; public class BitmapTest extends Activity { private int currentImage=0; String[] assetsImages; ImageView imageView; AssetManager assets; // asset资源管理引用变量 InputStream stream=null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.mian); imageView = (ImageView) findViewById(R.id.imageview); // 1.获取/res/assets目录下文件列表 try { assets = getAssets(); // 获取asset资源管理对象 assetsImages = assets.list(""); // 获取assets目录下的所有文件名存放至String数组中 stream=assets.open(assetsImages[currentImage]); //ImageView设置为Assets目录下的第一张图片 imageView.setImageBitmap(BitmapFactory.decodeStream(stream)); } catch (IOException e) { e.printStackTrace(); } // 2.为btn按钮注册事件监听器,实现循环图片切换功能 Button btn = (Button) findViewById(R.id.button); btn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { //a.累加数组下标currentImage if(!assetsImages[currentImage].endsWith("*.png") && !assetsImages[currentImage].endsWith("*.jpg") &&!assetsImages[currentImage].endsWith("*.gif")) { currentImage++; if(currentImage==assetsImages.length-3) //如果发现数组越界,重置currentImage { currentImage=0; } } //b.打开指定资源的输入流 InputStream stream = null; try { stream=assets.open(assetsImages[currentImage]); } catch (IOException e) { e.printStackTrace(); } //c.获取当前图片的BitmapDrawable对象 BitmapDrawable bitmapDrawable = (BitmapDrawable)imageView.getDrawable(); if(bitmapDrawable!=null && !bitmapDrawable.getBitmap().isRecycled()) { bitmapDrawable.getBitmap().recycle(); } imageView.setImageBitmap(BitmapFactory.decodeStream(stream)); } }); } }</span>
效果演示: