Android中如何创建自定义ListView

综述

随着搭载了Android系统的设备数量越来越普及,对Android系统应用开发有兴趣的开发者也越来越多。各种类型的应用中都常常会使用到ListView。Android系统预先定义了一些ListView的类型,可以在官方发布的API Demos中找到。不过由于往往需要使用自定义的ListView来满足不同应用的设计需要,因此有必要了解Android系统中创建并使用自定义ListView的方法。本文结合个人的一些经验,期望能尽可能简明易懂地对这个问题进行说明。

本文的目标读者是具有一定的Java语言和Android开发基础的开发者。

本文将对一个具有图片(ImageView)、文本(TextView)和可选框(CheckBox)三种控件的自定义ListView的代码进行注释与详解,以供读者举一反三,创建并使用自己的自定义ListView。

本文所使用的开发环境为:

  • Windows 7
  • Eclipse Java IDE Version 3.7 (Indigo)
  • Oracle Java SE JDK 6 Update 26
  • Android SDK Version 2.3.3, API 10

(以上并非必要环境。相兼容的操作系统和较低版本的软件也可以完成本项目。)

代码

ListViewExampleActivity.java

package org.breezesoft.listviewexample;
package org.breezesoft.listviewexample;

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

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

public class ListViewExampleActivity extends Activity {

	//声明所需变量
	private String items[];//ListView中每一个项目的文本内容
	private int colors[];//ListView中每一个项目的图片对应的URL
	private boolean checkboxstate[];//ListView中每一个项目的CheckBox的勾选状态
	private ListView listView;//声明ListView
	private List> itemList;//声明所需的映射表
	private ItemAdapter itemListAdapter;//声明所需的适配器

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

		//初始化数据,本范例中的ListView将有三条项目
		String item = "Red\nGreen\nBlue";
		items = item.split("\n");
		colors=new int[3];
		colors[0]=R.drawable.red;
		colors[1]=R.drawable.green;
		colors[2]=R.drawable.blue;
		checkboxstate=new boolean[3];
		checkboxstate[0]=false;
		checkboxstate[1]=false;
		checkboxstate[2]=false;
		
		refresh();//调用该函数将初始化后的数据填入列表,详见该函数

		//列表项目的按键监听
		listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
			@Override
			public void onItemClick(AdapterView parent, View view, int position, long id) {
				;//在这里依据需要添加所需的响应语句
			}
		});

	}

	//以下三个函数为活动生命周期相关函数,与本文主题无关
	@Override
	public void onResume() {
		super.onResume();
		refresh();
	}

	@Override
	public void onPause() {
		super.onPause();
	}

	@Override
	public void onStop() {
		super.onStop();
	}

	//以下两个函数为列表添加了上下文菜单(Context Menu),关于上下文菜单可参见博客中的其他文章
	@Override
	public void onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo menuInfo) {//初始化上下文菜单
		menu.setHeaderTitle(R.string.app_name);
		menu.add(0, 1, 0, R.string.app_name);
		menu.add(0, 2, 0, R.string.app_name);
	}

	@Override
	public boolean onContextItemSelected(MenuItem item) {
		AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
		switch (item.getItemId()) {//在这里添加需要的语句
		case 1:
			break;
		case 2:
			break;
		}
		return true;

	}

	//列表内容刷新函数
	private void refresh() {
		listView = new ListView(this);
		listView = (ListView) findViewById(R.id.list1);//指定在xml中描述的ListView

		itemList = new ArrayList>();
		//由之前初始化的数据进行填充
		for (int i = 0; i < items.length; i++) {
			Map map = new HashMap();
			map.put("IMG", colors[i]);//图片
			map.put("ITEMNAME", items[i]);//文本
			if (checkboxstate[i]) {//标识CheckBox状态的变量
				map.put("CHECKED", "t");
			} else {
				map.put("CHECKED", "f");
			}
			itemList.add(map);//添加一条项目
		}
		itemListAdapter = new ItemAdapter(this, itemList);
		listView.setAdapter(itemListAdapter);//应用经过数据填充的适配器
	}

	//修改CheckBox状态的函数,与本文主题无关
	public void setC(int position) {
		if (checkboxstate[position]) {
			checkboxstate[position] = false;
		} else
			checkboxstate[position] = true;
	}

	//自定义的适配器,是使用自定义ListView的关键
	public class ItemAdapter extends BaseAdapter {
		private List> itemList;
		private LayoutInflater mInflater;

		//以下为适配器的通用接口函数
		public ItemAdapter(Context context, List> til) {
			this.mInflater = LayoutInflater.from(context);
			itemList = til;
		}

		public int getCount() {
			return itemList.size();
		}

		public Object getItem(int arg0) {
			return null;
		}

		public long getItemId(int arg0) {
			return 0;
		}

		public View getView(int position, View convertView, ViewGroup parent) {
			final int cc = position;
			ViewHolder holder = null;
			if (convertView == null) {
				holder = new ViewHolder();
				convertView = mInflater.inflate(R.layout.itemrow, null);
				holder.tagcolor = (ImageView) convertView.findViewById(R.id.itemrowiamge);
				holder.itemname = (TextView) convertView.findViewById(R.id.itemrowtext);
				holder.cb = (CheckBox) convertView.findViewById(R.id.itemrowcb);
				convertView.setTag(holder);
			} else {
				holder = (ViewHolder) convertView.getTag();
			}

			//获取ViewHolder中所填入的数据
			holder.tagcolor.setBackgroundResource((Integer) itemList.get(position).get("IMG"));
			holder.itemname.setText((String) itemList.get(position).get("ITEMNAME"));
			holder.ckd = (String) itemList.get(position).get("CHECKED");

			//单个项目中的CheckBox的按键监听函数
			holder.cb.setOnClickListener(new View.OnClickListener() {
				public void onClick(View v) {
					setC(cc);//当被按下后调用函数改变状态
				}
			});
			if (holder.ckd.equals("t"))
				holder.cb.setChecked(true);
			else
				holder.cb.setChecked(false);
			return convertView;
		}
	}

}

.
.
ViewHolder.java

package org.breezesoft.listviewexample;

import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.TextView;

//ViewHolder类用以储存每一条项目所需的数据
public class ViewHolder {
	public ImageView tagcolor;//单条项目中的图片
	public TextView itemname;//单条项目中的文本
	public CheckBox cb;//单条项目中的CheckBox
	public String ckd;//单条项目中用以标识CheckBox状态的字符串变量
}

.
.
main.xml




	
		
	


.
.
itemrow.xml



	
	
	

.
.

说明

ListViewExampleActivity是本范例的主体。在onCreate函数中进行了准备工作,初始化了数据等,并提供了ListView的按键监听函数。在该类中包含了基于BaseAdapter 的自定义适配器ItemAdapter类。这是使用自定义ListView的关键。代码注释说明了各个部分的内容。其中getView()函数需要根据不同的自定义ListView的项目内容进行调整。本范例的项目包含图片、文本和CheckBox三项内容,因此getView()函数也相应地对这三项内容进行了操作。如果自定义的ListView项目包含更多内容,在这里进行相应的语句增添即可。

ViewHolder包含了单条项目中所要储存的数据。由于结构较为简单,故不多熬述。

main.xml是ListViewExampleActivity所使用的布局文件。在一个LinearLayout中包含了一个ListView。布局不是本文的主题,故在此不多熬述,可参见博客中的其他文章。

itemrow.xml是使用自定义ListView的另一关键。它使用一个RelativeLayout描述了单条项目中的图片、文本和CheckBox的相对位置关系。该内容亦不是本文的主题,更进一步的内容可参见博客中的其他文章。

简单地说,通过修改本范例中的refresh()函数、ItemAdapter中的getView()函数、ViewHolder类和itemrow.xml即可实现其他类型的ListView。

截图与资源

点此下载程序代码与资源

本文参加

第二届 Google 暑期大学生博客分享大赛 – 2011 Android 成长篇