目录
【例7-61】定义一个表示Gallery图片的适配器类 ImageGalleryAdapter
提示:ImageGalleryAdapter也可以使用List集合保存数据。
【例7-65】定义 Activity 程序,显示 Gallery
(3)Gallery和 ImageSwitcher两个组件联合使用
一、Gallery组件简单介绍
使用过Android手机的用户应该知道,在Android中可以使用一些软件方便地进行图片的拖拽浏览,这样的功能可以通过Gallery组件实现。使用 Gallery组件可以定义一组图片浏览框,如图7-37所示, 可以降低开发者对于图片浏览功能的开发难度
Gallery类的继承结构如下:
Gallery类提供的常用方法
如表7-20所示。
Gallery的实现
在使用Gallery设置图片集时需要使用setAdapter()方法,此时设置的是SpinnerAdapter接口的对象,
主要的功能::定义一组要显示的组件的适配器,而对于这种适配器操作有两种可选方式。
方式一:继承BaseAdapter类实现
用一个自定义的类直接继承SpinnerAdapter接口的子类 android.widget.BaseAdapter类实现,这样用户只需要覆写核心操作方法即可,不需要的方法可以不覆写。
方式二:直接使用SimpleAdapter类实现
下面分别演示如何采用这两种方式完成操作。
二、案例代码实现
(1)自定义适配器类的方式实现
如果要采用自定义适配器类的方式完成,可以直接覆写BaseAdapter类中的几个方法,如表7-21所示。
表7-21 BaseAdapter类的常用方法
【例7-61】定义一个表示Gallery图片的适配器类 ImageGalleryAdapter
package org.lxh.demo;
import android.content.Context;
import android.graphics.Color;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Gallery;
import android.widget.ImageView;
import android.widget.LinearLayout.LayoutParams;
/**
* 定义一个表示Gallery图片的适配器类:ImageGalleryAdapter
* @author luminal
*/
public class ImageGalleryAdapter extends BaseAdapter {
private Context myContext; // Context对象
private int imgRes[] = new int[] { R.drawable.ispic_a, R.drawable.ispic_b,
R.drawable.ispic_c, R.drawable.ispic_d, R.drawable.ispic_e };
public ImageGalleryAdapter(Context c) { // 接收Context
this.myContext = c;
}
@Override
public int getCount() { // 返回图片个数
return this.imgRes.length;
}
@Override
public Object getItem(int position) { // 取得指定位置的图片
return this.imgRes[position];
}
@Override
public long getItemId(int position) { // 取得指定位置的图片
return this.imgRes[position];
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView img = new ImageView(this.myContext);
img.setBackgroundColor(Color.BLACK);//背景颜色-黑色
img.setImageResource(this.imgRes[position]); // 给ImageView设置资源
img.setScaleType(ImageView.ScaleType.CENTER); // 居中显示
img.setLayoutParams(new Gallery.LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT)); // 布局参数
return img;
}
}
本程序首先将需要显示的5张图片分别保存在drawable-*文件夹中,然后将所有图片资源的
ID通过imgRes数组进行保存,再实现BaseAdapter类中所需要的相关方法即可。
提示:ImageGalleryAdapter也可以使用List集合保存数据。
在ImageGalleryAdapter类中,所有的资源是通过imgRes数组保存的,
如果用户觉得数组用不方便,也可以将其替换成List集合.
下面直接通过Gallery定义一个图片浏览操作,并在选中某张图片之后,通过android.widget.Toast类显示选中图片的资源编号。
【例7-62】在main.xml文件中定义组件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/MyLayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<!--
android:gravity="center_vertical"水平居中摆放组件
android:spacing="3px"显示的间距为3像素
-->
<Gallery
android:id="@+id/myGallery"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:spacing="3px" />
</LinearLayout>
本程序只在布局管理器中定义了一个普通的Gallery组件,而且设置了组件中各个图片项的间距为3像素(3px)
【例7-63】编写Activity程序,显示选中图片的信息
package org.lxh.demo;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Gallery;
import android.widget.Toast;
/**
* 编写Activity程序,显示选中图片的信息
* @author luminal
*/
public class MyGalleryDemo extends Activity {
private Gallery gallery = null; // 声明Gallery组件
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setContentView(R.layout.main);// 调用布局文件
this.gallery = (Gallery) super.findViewById(R.id.myGallery);// 取得组件
this.gallery.setAdapter(new ImageGalleryAdapter(this));// 设置图片集
this.gallery.setOnItemClickListener(new OnItemClickListenerImpl());// 设置单击事件
//this.gallery.setSelection(2);// 设置以第三项为中心
}
private class OnItemClickListenerImpl implements OnItemClickListener {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
Toast.makeText(MyGalleryDemo.this, "" + position,
Toast.LENGTH_SHORT).show();// 显示图片编号
}
}
}
本程序中首先通过findViewByld()方法取得了Gallery组件的对象,之后使用 setAdapter()方法将定义的Image图片数组进行转换,当用户选择了某张图片时,会通过Toast类将对应的图片编号进行短暂的显示。程序的运行效果如图7-38所示。
(2)使用 SimpleAdapter 类方式实现
釆用方式一操作,可以通过自定义适配器类的方式显示图片,除此之外,也可以直接釆用SimpleAdapter类的方式完成,通过自定义显示模板的方式显示所有的图片资源,但是考虑到有些用户有可能随时修改资源文件,所以本程序将采用反射机制加载所有的资源ID
提示:关于反射机制
本程序将使用java.lang.reflect.Field类动态地取出所有保存的图片资源,此部分内容可以参考《名师讲坛——Java开发实战经典》第15章的内容。
【例7-64】定义显示模板 grid_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#FFFFFF">
<!--
android:scaleType="center" 居中对齐
-->
<ImageView
android:id="@+id/img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="center"/>
</LinearLayout>
本程序直接采用了线性布局管理器,其中只定义了一个ImageView组件,而且所有的布局参数和组件参数与之前所编写的ImageGalleryAdapter类中的getView()方法返回的组件是一样 的,
即本程序将直接通过此配置文件替换掉 ImageGalleryAdapter类中的getView方法。
【例7-65】定义 Activity 程序,显示 Gallery
package org.lxh.demo;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Gallery;
import android.widget.SimpleAdapter;
import android.widget.Toast;
/**
* 定义 Activity 程序,显示 Gallery
* 釆用SimpleAdapter类的方式完成,
* 通过自定义显示模板的方式显示所有的图片资源
* @author luminal
*/
public class MyGalleryDemo extends Activity {
private Gallery gallery = null;// 声明Gallery组件
private List<Map<String, Integer>> list = new ArrayList<Map<String, Integer>>();
private SimpleAdapter simpleAdapter = null;// 适配器
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setContentView(R.layout.main);// 调用布局文件
this.initAdapter();// 初始化适配器
this.gallery = (Gallery) super.findViewById(R.id.myGallery);// 取得组件
this.gallery.setAdapter(this.simpleAdapter);// 设置图片集
this.gallery.setOnItemClickListener(new OnItemClickListenerImpl());// 设置单击事件
}
private class OnItemClickListenerImpl implements OnItemClickListener {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
Toast.makeText(MyGalleryDemo.this, "" + position,
Toast.LENGTH_SHORT).show(); // 显示图片编号
}
}
/**
* 初始化适配器
*/
public void initAdapter() {
//获取drawable目录下所有图片
Field[] fields = R.drawable.class.getDeclaredFields();
for (int x = 0; x < fields.length; x++) {
if (fields[x].getName().startsWith("ispic_")) { // 所有ispic_*命名的图片
Map<String, Integer> map = new HashMap<String, Integer>(); // 定义Map
try {
map.put("img", fields[x].getInt(R.drawable.class));// 设置图片资源
}catch (Exception e) {
e.printStackTrace();
}
this.list.add(map); // 保存Map,到 List集合里面
}
}
// 实例化SimpleAdapter
this.simpleAdapter = new SimpleAdapter(this,
this.list,// 要包装的数据集合
R.layout.grid_layout,// 要使用的显示模板
new String[] { "img" },// 定义要显示的 Map 的 Key
new int[] { R.id.img });// 与模板中的组件匹配
}
}
本程序中采用了 SimpleAdapter类完成了适配器的操作,而后定义了一个 initAdapter()方法,通过反射取得了所有资源中的图片信息,之后将所有以“ispic_*”命名的图片保存到了 List集合中, 再通过此集合为 SimpleAdapter类实例化,并显示所有的图片,程序的运行效果与图7-38 一致。
提示:开发中采用SimpleAdapter类完成
通过比校,读者应该清楚了自定义适配器类与SimpleAdapter类的使用区别及联系,而在开发中为了方便,大部分程序都会采用SimpleAdapter类的方式完成,这样可以很好地实现“代码和配置”相分离,而且与MVC设计模式的要求相吻合,而对于MVC设计模式不 清楚的读者,可以参考《名师讲坛——Java Web开发实战经典》一书。
对于自定义适配器类的操作形式一般在用户需要手工处理列表项的情况下发生,而且对于之前讲解的ListView组件,也可以采用自定义适配器的操作形式完成,这些都将在后面讲解。
以上只是完成了一个最简单的图片列表的功能,当用户选择某张图片之后,会利用Toast 组件显示用户选择图片的编号。
(3)Gallery和 ImageSwitcher两个组件联合使用
下面再开发一个更实用的组件,当用户从图片浏览框中选择了一张图片之后,可以在屏幕上将这张图片完整地显示出来,而此功能就可以将Gallery和 ImageSwitcher两个组件联合起来使用
【例7-66】在main.xml文件中定义组件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/MyLayout"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="bottom">
<ImageSwitcher
android:id="@+id/myImageSwitcher"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
<Gallery
android:id="@+id/myGallery"
android:gravity="center_vertical"
android:spacing="3px"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
<!--
android:spacing="3px" 各个列表项之间的间距
-->
</LinearLayout>
在本布局管理器中定义了一个ImageSwitcher和一个Gallery组件,当通过Gallery选择一张图片时,可以在ImageSwitcher中显示相关的图片。
【例7-67】定义Activity程序,进行图片显示
package org.lxh.demo;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Gallery;
import android.widget.ImageSwitcher;
import android.widget.ImageView;
import android.widget.LinearLayout.LayoutParams;
import android.widget.SimpleAdapter;
import android.widget.ViewSwitcher.ViewFactory;
/**
* 定义Activity程序,进行图片显示
* @author luminal
*/
public class MyGalleryDemo extends Activity {
private Gallery gallery = null; // 声明 Gallery组件
private List<Map<String, Integer>> list = new ArrayList<Map<String, Integer>>();
private SimpleAdapter simpleAdapter = null; // 适配器
private ImageSwitcher myImageSwitcher = null; // 图片切换
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setContentView(R.layout.main); // 调用布局文件
this.initAdapter(); // 初始化适配器
this.gallery = (Gallery) super.findViewById(R.id.myGallery); // 取得组件
this.myImageSwitcher = (ImageSwitcher) super
.findViewById(R.id.myImageSwitcher); // 取得组件
this.myImageSwitcher.setFactory(new ViewFactoryImpl()); // 设置图片工厂
this.gallery.setAdapter(this.simpleAdapter); // 设置图片集
this.gallery.setOnItemClickListener(new OnItemClickListenerImpl());// 设置单击事件
}
private class OnItemClickListenerImpl implements OnItemClickListener {
@SuppressWarnings("unchecked")
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
Map<String, Integer> map = (Map<String, Integer>) MyGalleryDemo.this.simpleAdapter
.getItem(position); // 取出Map
MyGalleryDemo.this.myImageSwitcher.setImageResource(map.get("img")); // 设置显示图片
}
}
/**
* 初始化适配器
*/
public void initAdapter() {
Field[] fields = R.drawable.class.getDeclaredFields();
for (int x = 0; x < fields.length; x++) {
if (fields[x].getName().startsWith("ispic_")) { // 所有ispic_*命名的图片
Map<String, Integer> map = new HashMap<String, Integer>(); // 定义Map
try {
map.put("img", fields[x].getInt(R.drawable.class));
} catch (Exception e) { // 设置图片资源
}
this.list.add(map); // 保存Map
}
}
this.simpleAdapter = new SimpleAdapter(this, // 实例化SimpleAdapter
this.list, // 要包装的数据集合
R.layout.grid_layout, // 要使用的显示模板
new String[] { "img" }, // 定义要显示的Map的Key
new int[] { R.id.img }); // 与模板中的组件匹配
}
/**
* 定义视图工厂类
*/
private class ViewFactoryImpl implements ViewFactory {
@Override
public View makeView() {
ImageView img = new ImageView(MyGalleryDemo.this); // 实例化图片显示
img.setBackgroundColor(0xFFFFFFFF); // 设置背景颜色
img.setScaleType(ImageView.ScaleType.CENTER); // 居中显示
img.setLayoutParams(new ImageSwitcher.LayoutParams( // 自适应图片大小
LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));// 定义组件
return img;
}
}
}
本程序在之前的代码基础上增加了 ImageSwitcher组件,当选择相关的图片之后会触发单击事件,而在此事件处理中,会首先根据用户选择图片的位置(position)从SimpleAdapter类中取得相关的配置项(Map),并取得对应的资源ID,之后使用setlmageResource()方法将选择的图片在 ImageSwitcher组件中进行显示。程序的运行效果如图7-39所示。