Gallery控件也可翻译为画廊组件,主要用于横向显示图像列表。我们通过查看Gallery类的继承结构,发现Gallery与我们之间讲解过的Spinner有共同的父类:AbsSpinner。从某种意义上来说,Gallery和Spinner都是一个列表框,只不过Spinner是一个垂直显示的列表模型,而Gallery则是一个水平显示的列表框。当然Gallery主要是通过用户拖动来展示一组图片或其它组件,而Spinner则是提供选择让用户选择。

Gallery的用户也与Spinner相似,只需要为它提供一个内容Adapter即可,该Adapter的getView()方法返回的View将作为Gallery组件的列表项。如果需要监听Gallery选择项的改变,则为Gallery添加OnItemSelectedListener监听器即可。

接下来,我们则通过一个例子来演示Gallery的使用。在这个例子中,我们首先通过一个Gallery显示一组图片,当我们点击图片的时候,在Gallery的下方通过ImageSwitcher显示我们点击的图片。

直接贴出代码:

package com.liuzhichao.gallery;

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.view.animation.AnimationUtils;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.Gallery;
import android.widget.ImageSwitcher;
import android.widget.ImageView;
import android.widget.SimpleAdapter;
import android.widget.ViewSwitcher.ViewFactory;

public class GalleryDemoActivity extends Activity {

	private Gallery myGallery;
	private SimpleAdapter simpleAdapter;
	private ImageSwitcher myImageSwitcher;
	private List <Map <String, Integer> >  list = new ArrayList <Map <String, Integer> > ();

	@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        myGallery = (Gallery)findViewById(R.id.myGallery);
        myImageSwitcher = (ImageSwitcher)findViewById(R.id.myImageSwitcher);

        initData();

        myGallery.setAdapter(simpleAdapter);
        myGallery.setSelection(list.size()/2); //默认显示中间的图片,避免第一次显示的时候左边留有空白

        myImageSwitcher.setFactory(new ViewFactory(){
			public View makeView() {
				ImageView imageView = new ImageView(GalleryDemoActivity.this);
				imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
				imageView.setLayoutParams(new ImageSwitcher.LayoutParams(130,170));
				return imageView;
			}

        });
        //设置图片更换的动画效果
        myImageSwitcher.setInAnimation(AnimationUtils.loadAnimation(this, android.R.anim.fade_in));
        myImageSwitcher.setOutAnimation(AnimationUtils.loadAnimation(this, android.R.anim.fade_out));

        //Gallery选择项改变事件处理
        myGallery.setOnItemSelectedListener(new OnItemSelectedListener() {

			public void onItemSelected(AdapterView <?>  parent, View view,
					int position, long id) {
				@SuppressWarnings("unchecked")
				Map <String, Integer>  map = (Map <String, Integer> ) parent.getAdapter().getItem(position);
				myImageSwitcher.setImageResource(map.get("img"));
			}

			public void onNothingSelected(AdapterView <?>  parent) {
				// TODO Auto-generated method stub

			}
		});
    }

	/**
	 * 初始化数据,由于图片名称是用规律的(都是以"t"开头) 所以可以使用反射加载图片
	 */
	private void initData() {
		Field[] fields = R.drawable.class.getDeclaredFields();
		for (int i = 0; i  < fields.length; i++) {
			// 找到drawable中以"t"开头的图片
			if (fields[i].getName().startsWith("t")) {
				Map <String, Integer>  map = new HashMap <String, Integer> ();
				try {
					map.put("img", fields[i].getInt(R.drawable.class));
				} catch (IllegalArgumentException e) {
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					new RuntimeException("数据实例化时发生异常");
				}
				list.add(map);
			}
		}
		//创建一个SimpleAdapter对象,该对象负责提供Gallery所需的每张图片
		simpleAdapter = new SimpleAdapter(GalleryDemoActivity.this, list,
				R.layout.imageview, new String[] { "img" },
				new int[] { R.id.myImageView });
	}

}

main.xml布局文件:

<?xml version="1.0" encoding="utf-8"?>
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"
    android:gravity="center" >
     <Gallery
        android:id="@+id/myGallery"
        android:spacing="2dp"
        android:gravity="center"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
         />
     <ImageSwitcher
        android:id="@+id/myImageSwitcher"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"/>
 </LinearLayout>

看一下运行效果:

 

在这个例子中,我们是通过SimpleAdapter来作为Gallery的数据适配器,同时我们发现上面的那个Gallery有一定的局限性,当拖动到最后一张图片时,则不能继续往后拖动。如何实现可以连续拖动的Gallery呢?下面我们能过自定义适配器来改进上面的Gallery。

首页我们需要自定义一个Adapter,假设命名为MyGalleryAdapter,让其BaseAdapter类。实行无限拖动的Gallery,主要注意下面两点,

1、getCount()返回一个较大的整数,这里我们取Integer.MAX_VALUE

2、在getView方法中通过取余来循环取得resIds数组中的图像资源ID。

下面是MyGalleryAdapter中的代码:

package com.liuzhichao.gallery;

import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Gallery;
import android.widget.Gallery.LayoutParams;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;

public class MyGalleryAdapter extends BaseAdapter {

	// 定义整型数组 即图片源
	public static int[] imgs = new int[] { R.drawable.t1, R.drawable.t2,
			R.drawable.t3, R.drawable.t4, R.drawable.t5, R.drawable.t6,
			R.drawable.t7, R.drawable.t8, R.drawable.t9 };

	// 定义Context
	private Context context;

	public MyGalleryAdapter(Context context) {
		this.context = context;
	}

	public int getCount() {
		//这里返回一个较大整数是为了实现Gallery的循环播放
		return Integer.MAX_VALUE;
	}

	public Object getItem(int position) {
		return position;
	}

	public long getItemId(int position) {
		return position;
	}

	public View getView(int position, View convertView, ViewGroup parent) {
		ImageView mImageView = new ImageView(context);
		// 给ImageView设置资源,要实现循环播放,这里需要对数据大小进行求余
		mImageView.setImageResource(imgs[position % imgs.length]);

		// 居中显示
		mImageView.setScaleType(ScaleType.CENTER);
		mImageView.setLayoutParams(new Gallery.LayoutParams(
				LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
		return mImageView;
	}

}

同时我们要对GalleryDemoActivity作出一点改进:

package com.liuzhichao.gallery;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.animation.AnimationUtils;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.Gallery;
import android.widget.ImageSwitcher;
import android.widget.ImageView;
import android.widget.ViewSwitcher.ViewFactory;

public class GalleryDemoActivity extends Activity {

	private Gallery myGallery;
	private ImageSwitcher myImageSwitcher;
	private List <Map <String, Integer> >  list = new ArrayList <Map <String, Integer> > ();

	@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        myGallery = (Gallery)findViewById(R.id.myGallery);
        myImageSwitcher = (ImageSwitcher)findViewById(R.id.myImageSwitcher);

        myGallery.setAdapter(new MyGalleryAdapter(GalleryDemoActivity.this));
        myGallery.setSelection(list.size()/2); //默认显示中间的图片,避免第一次显示的时候左边留有空白

        myImageSwitcher.setFactory(new ViewFactory(){
			public View makeView() {
				ImageView imageView = new ImageView(GalleryDemoActivity.this);
				imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
				imageView.setLayoutParams(new ImageSwitcher.LayoutParams(130,170));
				return imageView;
			}

        });
        //设置图片更换的动画效果
        myImageSwitcher.setInAnimation(AnimationUtils.loadAnimation(this, android.R.anim.fade_in));
        myImageSwitcher.setOutAnimation(AnimationUtils.loadAnimation(this, android.R.anim.fade_out));

        //Gallery选择项改变事件处理
        myGallery.setOnItemSelectedListener(new OnItemSelectedListener() {

			public void onItemSelected(AdapterView <?>  parent, View view,
					int position, long id) {

				myImageSwitcher.setImageResource(MyGalleryAdapter.imgs[position]);
			}

			public void onNothingSelected(AdapterView <?>  parent) {
				// TODO Auto-generated method stub

			}
		});
    }

}

运行后,我们发现效果一样,只是现在Gallery可以往后无限滚动,但是当往前滚动时,到达第一张图片后,则无法再滚动。可以说这也是一个不完美的地方。如果有哪位大侠解决此问题了的,还忘分享。