【Bitmap】—— 基础知识
【Bitmap能够解决的问题】
1、我们知道一般我们使用图片的话,都是使用保存在res/drawable/文件夹下的图片资源,
比如ImageView , 在布局文件中是 <ImageView android:src = "@drawable/picture">
如果在Java代码中则是 setImageResource(int resId)
2、那就会出现一个问题,如果我们想要使用SD卡存储器中图片文件作为ImageView的资源,这时候该怎么办呢?要完成这个问题,需要以下几步:
①将SD卡中的图片文件解析成Bitmap对象
②调用ImageView的 setImageBitmap (Bitmap m) 方法,为ImageView加载这个Bitmap对象
3、除此之外,将一张图片转换成Bitmap对象之后,就能够非常方便的对Bitmap中的图片进行变换,如:剪裁、旋转、缩放等变幻从而创建出新的Bitmap对象
【Bitmap基础】
1、Bitmap和BitmapDrawable之间的转化方法:
Bitmap代表一张位图,BitmapDrawable 里封装的图片就是一个Bitmap对象。开发者为了将一个Bitmap对象包装成一个BitmapDrawable对象,可以调用BitmapDrawable的构造方法:
//把一个Bitmap对象包装成BitmapDrawable
BitmapDrawable drawable = new BitmapDrawable(bitmap) ;
如果想要取出BitmapDrawable中的Bitmap对象的话,只需要调用BitmapDrawable的getBitmap()方法
Bitmap bitmap = drawable.getBitmap() ;
这样的话,我们就能够进行Bitmap和Drawable之间的转化
2、如何通过已有的Bitmap对象创建新的Bitmap对象
非常的方便就是使用Bitmap的下面的几个静态方法来创建:
createBitmap(Bitmap source ,int x, int y , int width , int height)
从原位图Bitmap指定的坐标点(x , y 参数)开始,从中“挖取” 宽width、 高height 的一块出来,创建新的Bitmap对象
createBitmap(Bitmap source , int x, int y , int width , int height , Matrix m , boolean filter)
createScaledBitmap(Bitmap src , int dstWidth , int dstHeight , boolean) 对src位图缩放成宽dstWidth 、高dstHeight的新位图
当然还有其他的方法,可以查阅文档
3、如何将不同的数据源解析成Bitmap对象
需要借助于BitmapFactory这个工具类中的静态方法
//从指定的字节数组的offset位置开始,将长度为length的字节数组数据解析成Bitmap对象
BitmapFactory.decodeByteArray(byte [ ] data , int offset, int length);
//从pathName指定的文件中解析出Bitmap对象
BitmapFactory.decodeFile(String pathName) ;
//从FileDescriptor对应的文件中解析成Bitmap对象
BitmapFactory.decodeFileDescriptor(FileDescriptor fd) ;
//根据给定的资源ID,从指定的资源中解析出Bitmap对象
BitmapFactory.decodeResource(Resuorces, int id)
//用于从指定的打开的图片文件的输入流中解析出Bitmap对象
BitmapFactory.decodeStream(InputStream is) ;
4、Bitmap的回收问题
由于手机的内存比较小,如果不停的去解析和创建Bitmap对象,可能由于由于前面所创建的Bitmap所占用的内存还没有被回收,而导致程序运行时引发OutOfMemory错误
Android为Bitmap提供了两个方法,用于检测当前的Bitmap对象是否已经被回收,以及强制回收当前的Bitmap对象:
//返回Bitmap对象是否已经被回收
boolean isRecycled()
//强制回收当前的Bitmap对象
void recycle()
【Bitmap实例】
我们要使用ViewPager来实现一个SD卡照片查看器:
先看看效果:
完整显示页面
手指滑动过渡页面
1 package com.penglee.imageviewer_test;
2
3 import java.io.File;
4 import java.io.IOException;
5 import java.util.ArrayList;
6 import java.util.List;
7
8 import android.app.Activity;
9 import android.graphics.BitmapFactory;
10 import android.os.Bundle;
11 import android.os.Environment;
12 import android.support.v4.view.ViewPager;
13 import android.widget.ImageView;
14 import android.widget.ImageView.ScaleType;
15 import android.widget.LinearLayout;
16 import android.widget.Toast;
17
18 public class MainActivity extends Activity {
19
20 static final String FOLDER_PATH = "/Picture/"; //SD卡中存有图片文件的文件夹
21 File [ ] fileList ; //保存指定文件夹下的所有文件
22
23 ViewPager viewPager ;
24
25 @Override
26 protected void onCreate(Bundle savedInstanceState) {
27 super.onCreate(savedInstanceState);
28 setContentView(R.layout.activity_main);
29
30 viewPager = (ViewPager)findViewById(R.id.viewPager);
31
32 //判定手机中是否插入了SD卡,并且本应用程序有读取权限
33 if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
34 //获取SD卡的目录
35 File sdCardDir = Environment.getExternalStorageDirectory() ;
36 try {
37
38 File targetFolder = new File(sdCardDir.getCanonicalFile()+FOLDER_PATH);
39 if(!targetFolder.exists())
40 {
41 Toast.makeText(MainActivity.this, "当前目录不存在", Toast.LENGTH_SHORT).show();
42 return ; //一旦执行了return ,那么onCreate方法中位于该return下面的代码就不会再执行了
43 }
44
45 fileList =targetFolder.listFiles() ;
46
47 if(fileList.length == 0) {
48 Toast.makeText(MainActivity.this, "当前目录下不存在文件", Toast.LENGTH_SHORT).show();
49 return ;//一旦执行了return ,那么onCreate方法中位于该return下面的代码就不会再执行了
50 }
51
52 } catch (IOException e) {
53 e.printStackTrace();
54 }
55 }
56
57 List<ImageView> pictures = new ArrayList<ImageView>() ;
58
59 LinearLayout.LayoutParams mParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
60 LinearLayout.LayoutParams.MATCH_PARENT);
61 for(int i =0 ; i < fileList.length ; i++){
62 if(fileList[i].getName().endsWith(".png")||fileList[i].getName().endsWith(".jpg")){
63 ImageView imageView = new ImageView(MainActivity.this);
64 imageView.setLayoutParams(mParams);
65 imageView.setScaleType(ScaleType.FIT_CENTER);
66 //关于如何将SD卡中的图片文件转化成Bitmap对象,从而能够让ImageView使用,参见Bitmap相关博文
67 imageView.setImageBitmap(BitmapFactory.decodeFile(fileList[i].getAbsolutePath()));
68 pictures.add(imageView);
69 }
70 }
71
72 //创建PictureAdapter
73 PictureAdapter pictureAdapter = new PictureAdapter(pictures);
74 //为ViewPager设置Adapter
75 viewPager.setAdapter(pictureAdapter);
76 }
77
78 }
1 package com.penglee.imageviewer_test;
2
3 import java.util.List;
4
5 import android.os.Parcelable;
6 import android.support.v4.view.PagerAdapter;
7 import android.view.View;
8 import android.widget.ImageView;
9 import android.support.v4.view.ViewPager ;
10
11 public class PictureAdapter extends PagerAdapter{
12
13 private List<ImageView> pictureViews ;
14
15 public PictureAdapter(List<ImageView> list){
16 this.pictureViews = list ;
17 }
18
19 //销毁arg1位置的界面
20 @Override
21 public void destroyItem(View arg0, int arg1, Object arg2) {
22 ((ViewPager) arg0).removeView(pictureViews.get(arg1));
23 }
24
25 @Override
26 public void finishUpdate(View arg0) {
27 // TODO Auto-generated method stub
28 }
29
30 //获得当前界面数
31 @Override
32 public int getCount() {
33 if (pictureViews != null)
34 {
35 return pictureViews.size();
36 }
37 return 0;
38 }
39
40
41 //初始化arg1位置的界面
42 @Override
43 public Object instantiateItem(View arg0, int arg1) {
44
45 ((ViewPager) arg0).addView(pictureViews.get(arg1), 0);
46 return pictureViews.get(arg1);
47 }
48
49 //判断是否由对象生成界面
50 @Override
51 public boolean isViewFromObject(View arg0, Object arg1) {
52 return (arg0 == arg1);
53 }
54
55 @Override
56 public void restoreState(Parcelable arg0, ClassLoader arg1) {
57 // TODO Auto-generated method stub
58
59 }
60
61 @Override
62 public Parcelable saveState() {
63 // TODO Auto-generated method stub
64 return null;
65 }
66
67 @Override
68 public void startUpdate(View arg0) {
69 // TODO Auto-generated method stub
70
71 }
72 }
1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
2 xmlns:tools="http://schemas.android.com/tools"
3 android:layout_width="match_parent"
4 android:layout_height="match_parent"
5 tools:context="com.penglee.imageviewer_test.MainActivity" >
6
7 <!-- 加载ViewPaper -->
8 <android.support.v4.view.ViewPager
9 android:id="@+id/viewPager"
10 android:layout_width="match_parent"
11 android:layout_height="match_parent">
12
13 </android.support.v4.view.ViewPager>
14
15
16 </RelativeLayout>