使用简单图片

      前面的Android应用中已经大量使用了简单图片,图片不仅可以使用ImageView来显示,也可作为Butto、Window的背景。从广义的角度来看,Android应用中的图片不仅包括*.png、*.jpg、*.gif等各种格式的位图,也包括使用XML资源定义的各种Drawable对象。

      使用Drawable对象

        为Android应用增加了Drawable资源之后,Android SDK会为这份资源在R清单文件中创建一个索引项:R.drawable.file_name。

        接下来既可在XML资源文件中通过@drawable/file_name来访问该Drawable对象,也可在Java代码中通过R.drawable.file_name来访问该Drawable对象。

        需要指出的是,R.drawable.file_name是一个int类型的常量,它只代表Drawable对象的ID,如果Java程序中需要获取实际的Drawable对象,既可调用Resources的getDrawable(int id)方法来获取。

        Bitmap和BitmapFactory

        Bitmap代表一张位图,BitmapDrawable里封装的图片就是一个Bitmap对象。开发者为了把一个Bitmap对象包装成BitmapDrawable对象,可以调用BitmapDrawable的构造器:

        //把一个Bitmap对象包装成BitmapDrawable对象

       BitmapDrawable drawable=new BitmapDrawable(bitmap);

      如果需要获取BitmapDrawable所包装的Bitmap对象,则可调用BitmapDrawable的getBitmap()方法,如下面代码所示:

       //获取一个BitmapDrawable所包装的Bitmap对象

      Bitmap bitmap=drawable.getBitmap();

      除此之外,Bitmap还提供了一些静态方法来创建新的Bitmap对象,例如如下常用方法。

  •  createBitmap(Bitmap source,int x,int y,int width,int height):从源位图source的指定坐标点(给定x、y)开始,从中“挖取”宽width、高height的一块出来,创建新的Bitmap对象。
  • createScaledBitmap(Bitmap src,int dstWidth,int dstHeight,boolean filter):对源位图src进行缩放,缩放成宽dstWidth、高dstHeight的新位图。
  • createBitmap(int width,int height,Bitmap.Config config):创建一个宽width、高height的新位图。
  • createBitmap(Bitmap source,int x,int y,int width,int height,Matrix m,boolean filter):从源位图source的指定坐标点(给定x,y)开始,从中“挖取”宽width、高height的一一块出来,创建新的Bitmap对象。并按Matrix指定的规则进行变换。    

    BitmapFactory是一个工具类,它用于提供大量的方法,这些方法可用于从不同的数据源来解析、创建Bitmap对象。BitmapFactory包含了如下方法。

  • decodeByteArray(byte[] data,int offset,int length):从指定字节数组的offset位置开始,将长度为lenth的字节数组解析成Bitmap对象。
  • decodeFile(String pathName):从pathName指定的文件中解析、创建Bitmap对象。
  • decodeFileDescriptor(FileDescriptor fd):用于从FieDescriptor对应的文件中解析、创建Bitmap对象。
  • decodeResource(Resource res,int id):用于根据给定的资源ID从指定的资源中解析、创建Bitmap对象。 
  • decodeStream(InputStream is):用于从指定输入流中解析、创建Bitmap对象。

      大部分时候,我们只要把图片放在/res/drawable-mdpi目录下,就可以在程序中通过该图片对应的资源ID来获取封装该图片的Drawble对象。但由于手机系统的内存比较小,如果系统不停的去解析、创建Bitmap对象,可能由于前面创建Bitmap所占用的内存还没有回收,而导致程序运行时引发OutOfMemory错误。

     Android为Bitmap提供了两个方法来判断他是否已回收,以及强制Bitmap回收自己。

  • boolean isRecycled():返回该Bitmap对象是否已被回收。
  • void recycle():强制一个Bitmap对象立即回收自己。

     除此之外,如果Android应用需要访问其他存储路径(比如SD卡中)里的图片,都需要借助于BitmapFactory来解析、创建Bitmap对象。

    下面开发一个查看/assets/目录下图片的图片查看器,该程序界面十分简单,只包含一个ImageView和一个按钮,但用户单击该按钮时程序会自动搜寻/assets/目录下的下一张图片。

    界面布局代码如下:

   

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
  <Button android:id="@+id/next"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:text="下一张图片"/>
  <ImageView android:id="@+id/image"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:scaleType="fitCenter"/>

</LinearLayout>

该程序的代码如下:
 

package com.example.studydrawable;

import java.io.IOException;
import java.io.InputStream;

import android.os.Bundle;
import android.app.Activity;
import android.content.res.AssetManager;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;

public class BitmapTest extends Activity {
     
    String[] images=null;
    AssetManager assets=null;
    int currentImg=0;
    ImageView image;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_bitmap_test);
        image=(ImageView)findViewById(R.id.image);
        try{
            assets=getAssets();
            //获取/assets/目录下所有文件
            images=assets.list("");
        }
        catch(IOException e)
        {
         e.printStackTrace();
        }
        //获取bn按钮
        final Button next=(Button)findViewById(R.id.next);
        //为bn按钮绑定事件监听器,该监听器将会查看下一张图片
        next.setOnClickListener(new OnClickListener(){

            @Override
            public void onClick(View source) {
                // TODO Auto-generated method stub
                //如果发生数组越界
                if(currentImg>=images.length)
                {
                    currentImg=0;
                }
                //找到下一张图片
                while(!images[currentImg].endsWith(".png")
                        &&!images[currentImg].endsWith(".jpg")
                        &&!images[currentImg].endsWith(".gif"))
                {
                    currentImg++;
                    //如果已经发生数组越界
                    if(currentImg>=images.length)
                    {
                        currentImg=0;
                    }
                }
                InputStream assetFile=null;
                try
                {
                    //打开指定资源对应的输入流
                    assetFile=assets.open(images[currentImg++]);
                }
                catch(IOException e)
                {
                    e.printStackTrace();
                }
                BitmapDrawable bitmapDrawable=(BitmapDrawable)image.getDrawable();
                //如果图片还未回收,先强制回收该图片
                if(bitmapDrawable!=null&&!bitmapDrawable.getBitmap().isRecycled())//
                {
                    bitmapDrawable.getBitmap().recycle();
                }
                //改变ImageView显示的图片
                image.setImageBitmap(BitmapFactory.decodeStream(assetFile));//
            }});
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.bitmap_test, menu);
        return true;
    }
    
}

   上面程序中①号粗体字代码用于判断当前ImageView所显示的图片是否已被回收,如果该图片还未回收,系统强制回收该图片;程序的②好粗体字代码调用了BitmpFactory从指定输入流解析、并创建Bitmap对象。

 

     

posted @ 2013-11-29 13:50  TealerProg  Views(378)  Comments(0Edit  收藏  举报