【IT168技术】使用Android中的Intents和自带的Gallery图库,用户可以从移动设备中选取喜欢的照片。在本教程中,我们将学习如何使用Gallery图库进行用户图片的自定义选择,并且会进行一些操作界面上的改进,以方便用户对图片进行选择。本文的阅读对象为有一定Android基础知识的读者。
下面进一步讲解本文程序要实现的功能。首先会使用Android内置的Gallery图库功能,显示一系列的图片缩略图。当用户长按这些缩略图中的某一张时,将会弹出选择窗口,提示用户选择图库本身已经有的图片还是重新从文件管理器中选择。当用户选择图片后,会在横向的图片列表中看到新加入的图片。用户可以点某张图片,就会在下方看到图片的完整大图。
步骤1 建立Android 工程
首先,建立一个Android工程,选择的Android SDK版本为2.3或以上,类的文件名为PicSelectActivity,然后在文件开始部分导入以下的类库
import android.content.Context;
import android.content.Intent;
import android.content.res.TypedArray;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.BaseAdapter;
import android.widget.Gallery;
import android.widget.ImageView;
然后在初始化部分,增加如下代码所示的变量,进行系统的一些参数设置:
//selection intent的参数
private final int PICKER = 1;
//保存当前选择的是第几张图片
private int currentPic = 0;
//gallery对象
private Gallery picGallery;
//用来显示大图的imageview控件
private ImageView picView;
上面的代码中,第一个参数PICKER,是用来标示当用户选择了图片并且返回到界面时的图片选择器。当用户长按缩略图中的某张图片时,需要使用currentPic来记录用户选择的是哪张图片。
在manifest文件中,增加如下代码部分:
android:configChanges="orientation|keyboardHidden"
这将让设备在方向变换的情况下依然能导入图片。接下来,我们在资源文件
“res/values/strings.xml”中,进行一些修改,以满足界面上的显示需要:
<string name="select_intro">Long-press a thumbnail to add an image</string>
<string name="show_intro">Press a thumbnail to display at larger size</string>
步骤2 设计界面
下面我们开始设计应用类的实际功能。首先我们要对主要的界面进行设计,打开main.xml,添加上文本框控件,代码如下:
android:layout_height="wrap_content"
android:padding="5dp"
android:text="@string/select_intro"
android:gravity="center"
android:textStyle="bold" />
然后再增加gallery图库控件,如下代码:
android:id="@+id/gallery"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
再增加其他界面上的提示信息的文本标签控件,以及最下方的用来显示大图的imageview控件,如下:
android:layout_height="wrap_content"
android:gravity="center"
android:padding="5dp"
android:textStyle="italic"
android:text="@string/show_intro" />
android:id="@+id/picture"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:contentDescription="@string/picture" />
我们还需要在资源文件夹中,对样式进行定义,在res/values目录下,新
建立文件attrs.xml,代码如下:
这里我们引用了android本身的一些样式,并将会在稍后的Java代码中引用到。最后我们在oncreate事件中,首先获得对gallery控件和imageview控件的引用:
picView = (ImageView) findViewById(R.id.picture);
picGallery = (Gallery) findViewById(R.id.gallery);
${PageNumber}步骤3 创建图片适配器
接下来,我们为了要重新设计图片显示的功能,必须先建立一个图片适配器的类,这个类是继承BaseAdapter基类的,结构如下:
public class PicAdapter extends BaseAdapter {
}
在这个类中,我们将提供一些BaseAdapter需要的方法,稍后也会新增加一些自定义的方法,首先先增加一些实例变量:
//默认的背景参数
int defaultItemBackground;
//gallery图库的上下文变量
private Context galleryContext;
//显示图片的数组
private Bitmap[] imageBitmaps;
//在图库中的一个空白的占位符
Bitmap placeholder;
其中第一个参数表示的是之前在attrs.xml中定义的Android Gallery的背景颜色。第二个参数Context变量表示的是当新增图片时的用户界面的上下文。而Bitmap数组存放的是需要显示的图片集合。一开始的时候,使用一个placeholder的占位图片,因为用户一开始并没有选择图片。
接下来是编写构造函数,代码如下:
public PicAdapter(Context c) {
//实例化context上下文
galleryContext = c;
//创建bitmap数组
imageBitmaps = new Bitmap[10];
//设置placeholder的图片
placeholder = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
}
在构造函数中,首先实例化了Context上下文变量和Bitmap数组。我们打算显示10张图片,当然读者可以随意修改,为了演示的方便,这里只是使用了创建Android工程时默认的图标作为每一张图片的内容,如果要使用其他图片的话,只需要把图片保存在drawable文件夹下,并且修改decodeResource这一行的代码,将R.drawable.ic_launcher中的ic_launcher更换为需要显示的文件名就可以了。
接下来我们通过for循环,为图片数组中的每个元素赋值,代码如下:
for(int i=0; i
imageBitmaps[i]=placeholder;
并且设置gallery的背景颜色,这里调用的是attrs.xml中设置的gallery背景边框值,代码如下:
TypedArray styleAttrs = galleryContext.obtainStyledAttributes(R.styleable.PicGallery);
defaultItemBackground = styleAttrs.getResourceId(
R.styleable.PicGallery_android_galleryItemBackground, 0);
styleAttrs.recycle();
我们需要另外新编写若干方法,以扩展Base Adapter类,首先是getcount方法,以返回图片数组的条数:
public int getCount() {
return imageBitmaps.length;
}
//返回指定位置的对象
public Object getItem(int position) {
return position;
}
//返回指定位置对象的id
public long getItemId(int position) {
return position;
}
不用担心,以上都是简单的标准方法,下面的是一个稍微复杂的方法,代码为:
public View getView(int position, View convertView, ViewGroup parent) {
//创建imageview
ImageView imageView = new ImageView(galleryContext);
//指定要显示哪一张用户选定的图的大图
imageView.setImageBitmap(imageBitmaps[position]);
//设置图片的属性大小
imageView.setLayoutParams(new Gallery.LayoutParams(300, 200));
//设置显示区域的比例
imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
//设置图片的背景色
imageView.setBackgroundResource(defaultItemBackground);
//返回视图
return imageView;
}
在getView方法中,我们定义了在图片显示控件中,将要显示哪一张用户选择的图片的大图,并且设置要显示图片的大小,比例属性等,这些用户都可以修改代码进行修改,这里的代码设置了300*200的图片大小,并且设置了图片的背景色。
接下来,我们要返回oncreate方法中,要对编写好的图片适配器进行实例化了,在oncreate方法中,编写如下代码:
imgAdapt = new PicAdapter(this);
//设置图库控件的适配器
picGallery.setAdapter(imgAdapt);
这个时候运行程序,效果如下:
${PageNumber}步骤4 让用户选择图片
在这个程序中,当用户长按图片列表中的某张图片时,将会让用户新增或者重新选择图片,这个时候我们需要在oncreate事件中,监听长按的事件,代码如下:
picGallery.setOnItemLongClickListener(new OnItemLongClickListener() {
public boolean onItemLongClick(AdapterView parent, View v, int position, long id) {
}
});
这里设置了一个监听长按事件的监听器,在其中的onItemLongClick事件中,编写如下代码:
currentPic = position;
//take the user to their chosen image selection app (gallery or file manager)
//弹出选择框,询问用户使用图库还是文件管理器选择图片
Intent pickIntent = new Intent();
pickIntent.setType("image/*");
pickIntent.setAction(Intent.ACTION_GET_CONTENT);
//在onActivityResult事件中获得返回的图片数据
startActivityForResult(Intent.createChooser(pickIntent, "Select Picture"), PICKER);
return true;
在上面的代码中,首先记录了用户在图片列表中选择的是第几张图片,然后新建立了Intent,将调用用户手机本身的图片浏览程序,让用户去选择图片,比如调用图库浏览器或者普通的文件管理工具,通过设置intent中的ACTION_GET_CONTENT,会将用户选择的图片数据返回。由于通过使用了
startActivityForResult方法调用intent,所以必须在Activity中的
onActivityResult方法中处理返回的数据。
至于调用哪个图片选择器选择图片,取决于用户手机上安装的应用,比如下图中是其中的一种情况:
${PageNumber}步骤5 处理用户选定并返回的图片
当用户选择了图片后,就要将选择的图片数据带回,将在onActivityResult方法中进行处理,代码如下:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
}
if (resultCode == RESULT_OK) {
// 检查是否从图片选择器中返回
if (requestCode == PICKER) {
//导入图片
}
}
super.onActivityResult(requestCode, resultCode, data);
}
在这里,我们检查是否接收了合法的数据并且数据是从图片选择的intent中返回的,如果是的话,则导入用户选择的图片,代码如下:
Uri pickedUri = data.getData();
这里首先是获得返回的所有的数据,这些数据都是以uri的形式所定义的。
接着再声明若干变量,如下:
Bitmap pic = null;
//定义图片路径
String imgPath = "";
接下来是获得图片路径的代码,如下:
String[] medData = { MediaStore.Images.Media.DATA };
//查询数据
Cursor picCursor = managedQuery(pickedUri, medData, null, null, null);
if(picCursor!=null)
{
//获得图片的路径
int index = picCursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
picCursor.moveToFirst();
imgPath = picCursor.getString(index);
}
else
imgPath = pickedUri.getPath();
这里首先调用了Android封装的多媒体API接口,使用managedQuery方法取查询数据,然后通过if else取判断是否图片选自Android图库本身还是来自文件选择器,最后获得图片文件的路径。
${PageNumber}步骤6 根据情况调节选定图片的大小
在实际应用中,由于用户的图片都很大,因此为了节省设备的资源,我们必须在将图片读入到设备前,进行必要的缩减工作,依然在onActivityResult方法中,加入如下代码:
if(pickedUri!=null) {
int targetWidth = 600;
int targetHeight = 400;
}
这里设置了最大允许图片的尺寸,接着在如下的代码中,首先设置了bitmap的options选项,先计算读取的图片的当前大小:
BitmapFactory.Options bmpOptions = new BitmapFactory.Options();
bmpOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(imgPath, bmpOptions);
int currHeight = bmpOptions.outHeight;
int currWidth = bmpOptions.outWidth;
然后设置一个变量去保存新的样例图片的尺寸比例:
int sampleSize = 1;
通过下面的代码判断当前的图片是否超过规定的尺寸大小,如果超过了,则进行比例的缩略:
if (currHeight>targetHeight || currWidth>targetWidth)
{
if (currWidth>currHeight)
sampleSize = Math.round((float)currHeight/(float)targetHeight);
else
sampleSize = Math.round((float)currWidth/(float)targetWidth);
}
再根据新的缩略图设置其参数,并且设置新的图片为我们缩略后的尺寸,其中pic变量存放的就是经过实际缩略后的小图的对象了。
bmpOptions.inSampleSize = sampleSize
bmpOptions.inJustDecodeBounds = false;
pic = BitmapFactory.decodeFile(imgPath, bmpOptions);
${PageNumber}步骤7 将缩略后的图片添加到gallery图库中去
接下来,我们要把缩略后的图片添加到gallery图库中去,这个时候,我们在PicAdapter的内部类中,增加一个助手方法,如下:
public void addPic(Bitmap newPic)
{
imageBitmaps[currentPic] = newPic;
}
这里传入的参数是Bitmap类型,就是将用户选择好的图片,设置到imageBitmaps数组中去,再在on ActivityResult方法中增加如下调用的代码:
imgAdapt.addPic(pic);
picGallery.setAdapter(imgAdapt);
这样,当用户选择了要选择的图片后,将自动剪裁图片,并马上会在picGallery的图片库控件中马上显示出来。
${PageNumber}步骤8 实现查看大图的功能
最后,我们需要实现的是当用户单击图片列表中的某张小图时,会在下方显示出其大图的功能。这个分两个步骤,首先是当用户新添加图片后,希望马上在屏幕下方的图片显示区域,显示出新增加的图片的大图,代码如下,注意添加在picGallery.setAdapter(imgAdapt)这句代码后:
picView.setImageBitmap(pic);
picView.setScaleType(ImageView.ScaleType.FIT_CENTER);
接下来,要实现的是用户单击图片列表中的某张小图时,会在下方显示出其大图的功能,这需要在PicAdapter内部类中,增加一个助手方法getPic,代码如下:
public Bitmap getPic(int posn)
{
return imageBitmaps[posn];
}
其功能是获得用户点选的是哪一张图片。然后在oncreate方法中,添加如下代码:
picGallery.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView parent, View v, int position, long id) {
picView.setImageBitmap(imgAdapt.getPic(position));
}
});
上面的代码中,在gallery图库中的每一项进行点选时,都会触发该事件,接着调用imgAdapt.getPic方法获得要显示的大图,放置在picView控件中进行显示。
步骤9 运行程序
现在我们已经完成了程序,通过运行观察实际效果,运行后,可以通过长按图片列表中的某张图,从而重新可以通过图库或者文件管理器选择图片,选择后的图片会以缩略图的形式显示在列表中,当单击某张图片时,会在屏幕下方像是其大图,如下图:
小结
在本文中,带领读者一步步,学习了如何做一个带缩略图列表的小型图片浏览器,用户可以从中学到如何导入图片,如何做图片缩略图以及对gallery图库的编程,读者可以进一步进行深入修改和学习。