网格式图
GridView
是一种用二维的,可以滚动的表格来显示项目的 ViewGroup
。使用 ListAdapter 后网格项目会自动插入到布局中。
请查阅 Building Layouts with an Adapter 了解如何使用适配器动态插入视图。
事例
在这个指南里,你将创建一个缩略图的表格。当有项目被选中时,会弹出一个显示图片位置的提示框消息。
- 创建一个新的名为 HelloGridView 的工程。
- 找一些你想用的图片或从这里下载(download these sample images)事例图片。把图片保存到工程的res/drawable/目录。
- 打开
res/layout/main.xml
文件,然后插入下面的内容:<?xml version="1.0" encoding="utf-8"?> <GridView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/gridview" android:layout_width="fill_parent" android:layout_height="fill_parent" android:columnWidth="90dp" android:numColumns="auto_fit" android:verticalSpacing="10dp" android:horizontalSpacing="10dp" android:stretchMode="columnWidth" android:gravity="center" />
这个
GridView
会填充整个屏幕。属性的意思相当明显。请查阅 GridView 参考文档了解更多关于有效属性的信息。 - 打开
HelloGridView.java
,然后在 onCreate() 方法内插入下面的代码:
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); GridView gridview = (GridView) findViewById(R.id.gridview); gridview.setAdapter(new ImageAdapter(this)); gridview.setOnItemClickListener(new OnItemClickListener() { public void onItemClick(AdapterView<?> parent, View v, int position, long id) { Toast.makeText(HelloGridView.this, "" + position, Toast.LENGTH_SHORT).show(); } }); }
在内容视图设置为main.xml后,使用 findViewById(int) 可以从布局中捕获
GridView
。setAdapter()
方法然后会为所有在表格中显示的项目设置自定义适配器(ImageAdapter)作为数据源。下一步会创建这个ImageAdapter
。往 setOnItemClickListener() 方法内传递一个新建的 AdapterView.OnItemClickListener 后就能在表格里的项目被点击时做出一些反应。这个匿名类定义了
onItemClick()
回调方法来显示一个Toast
,在其中展示被选中项目的索引位置(从零开始)(在真实世界的场景下,这个位置可以被用来为某些其他任务获取全尺寸的图片)。 - 创建一个继承 BaseAdapter 的名为
ImageAdapter
的全新类:
public class ImageAdapter extends BaseAdapter { private Context mContext; public ImageAdapter(Context c) { mContext = c; } public int getCount() { return mThumbIds.length; } public Object getItem(int position) { return null; } public long getItemId(int position) { return 0; } // 为每个被适配器引用的项目创建一个新的ImageView public View getView(int position, View convertView, ViewGroup parent) { ImageView imageView; if (convertView == null) { // 如果不是回收的,初始化某些属性 imageView = new ImageView(mContext); imageView.setLayoutParams(new GridView.LayoutParams(85, 85)); imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); imageView.setPadding(8, 8, 8, 8); } else { imageView = (ImageView) convertView; } imageView.setImageResource(mThumbIds[position]); return imageView; } // 图片的引用 private Integer[] mThumbIds = { R.drawable.sample_2, R.drawable.sample_3, R.drawable.sample_4, R.drawable.sample_5, R.drawable.sample_6, R.drawable.sample_7, R.drawable.sample_0, R.drawable.sample_1, R.drawable.sample_2, R.drawable.sample_3, R.drawable.sample_4, R.drawable.sample_5, R.drawable.sample_6, R.drawable.sample_7, R.drawable.sample_0, R.drawable.sample_1, R.drawable.sample_2, R.drawable.sample_3, R.drawable.sample_4, R.drawable.sample_5, R.drawable.sample_6, R.drawable.sample_7 }; }
首先,实现一些从 BaseAdapter 继承的必要方法。构造方法和
getCount()
不用多加说明了。通常getItem(int)
应该返回适配器内指定位置的实际对象,但是在这个事例中被忽略了。同样地,getItemId(int)
应该返回项目的行id,但是这里不需要。第一种必要的方法是
getView()
。这个方法为每个添加到 ImageAdapter 的图片创建新的View
。当这个方法被调用,就会传递进入一个 View,通常它是一个循环使用的对象(至少在该方法被调用一次后),所以需要检查该对象是否为空。若为空,实例化一个 ImageView,然后为图片的需求使用合适的属性配置:setLayoutParams(ViewGroup.LayoutParams)
设置视图的高度和宽度—这样可以确保无论图片有多大,每张图片都会被缩放和裁剪到合适大小来匹配这些尺寸。setScaleType(ImageView.ScaleType)
声明图片应该向中间裁剪(如果必要的话)。setPadding(int, int, int, int)
定义所有侧边的内边距(注意,因为图片有不同的宽高比,如果图片无法匹配ImageView指定的尺寸的话,越少的内边距会使图片裁剪的更多。)
如果传递给 getView() 的
View
不为空,那么本地ImageView
会使用循环使用的 View 对象来初始化。在
getView()
方法最后, 传入方法的position
整型值被用来从作为 ImageView 图片资源的 mThumbIds数组中选择图片。剩下的就是定义
mThumbIds
数组的图片资源。 - 运行程序。
调整 GridView
和 ImageView
的属性来测试他们的行为。例如,尝试使用 setAdjustViewBounds(boolean) 而不是 setLayoutParams(ViewGroup.LayoutParams)
。