技术开发 频道

一步步做Android增强型图片浏览器

  【IT168技术】使用Android中的Intents和自带的Gallery图库,用户可以从移动设备中选取喜欢的照片。在本教程中,我们将学习如何使用Gallery图库进行用户图片的自定义选择,并且会进行一些操作界面上的改进,以方便用户对图片进行选择。本文的阅读对象为有一定Android基础知识的读者。

  下面进一步讲解本文程序要实现的功能。首先会使用Android内置的Gallery图库功能,显示一系列的图片缩略图。当用户长按这些缩略图中的某一张时,将会弹出选择窗口,提示用户选择图库本身已经有的图片还是重新从文件管理器中选择。当用户选择图片后,会在横向的图片列表中看到新加入的图片。用户可以点某张图片,就会在下方看到图片的完整大图。

  步骤1 建立Android 工程

  首先,建立一个Android工程,选择的Android SDK版本为2.3或以上,类的文件名为PicSelectActivity,然后在文件开始部分导入以下的类库

import android.app.Activity;
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="picture">Picture</string>
<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>
${PageNumber}

  步骤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);

  这个时候运行程序,效果如下:

步骤3 创建图片适配器

${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方法中处理返回的数据。

  至于调用哪个图片选择器选择图片,取决于用户手机上安装的应用,比如下图中是其中的一种情况:

步骤4 让用户选择图片

${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 运行程序

  现在我们已经完成了程序,通过运行观察实际效果,运行后,可以通过长按图片列表中的某张图,从而重新可以通过图库或者文件管理器选择图片,选择后的图片会以缩略图的形式显示在列表中,当单击某张图片时,会在屏幕下方像是其大图,如下图:

步骤8 实现查看大图的功能并运行

  小结

  在本文中,带领读者一步步,学习了如何做一个带缩略图列表的小型图片浏览器,用户可以从中学到如何导入图片,如何做图片缩略图以及对gallery图库的编程,读者可以进一步进行深入修改和学习。

1
相关文章