综述
随着搭载了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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 |
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<Map<String, Object>> 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<Map<String, Object>>(); //由之前初始化的数据进行填充 for (int i = 0; i < items.length; i++) { Map<String, Object> map = new HashMap<String, Object>(); 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<Map<String, Object>> itemList; private LayoutInflater mInflater; //以下为适配器的通用接口函数 public ItemAdapter(Context context, List<Map<String, Object>> 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
1 2 3 4 5 6 7 8 9 10 11 12 13 |
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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<?xml version="1.0" encoding="utf-8"?> <LinearLayout android:id="@+id/LinearLayout01" xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <LinearLayout android:orientation="vertical" android:paddingLeft="1dip" android:layout_height="fill_parent" android:layout_width="fill_parent" android:gravity="center_vertical"> <ListView android:layout_height="fill_parent" android:cacheColorHint="#00000000" android:layout_width="fill_parent" android:id="@+id/list1"></ListView> </LinearLayout> </LinearLayout> |
.
.
itemrow.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout android:layout_width="fill_parent" android:layout_height="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android" android:cacheColorHint="#00000000" android:orientation="horizontal"> <ImageView android:drawable="@drawable/icon" android:id="@+id/itemrowiamge" android:paddingLeft="3dip" android:cacheColorHint="#00000000" android:layout_width="wrap_content" android:layout_height="wrap_content"></ImageView> <TextView android:id="@+id/itemrowtext" android:layout_width="wrap_content" android:maxLines="1" android:maxWidth="350dip" android:paddingLeft="10dip" android:textSize="20sp" android:textColor="#FFFFFFFF" android:layout_toRightOf="@id/itemrowiamge" android:layout_height="wrap_content"></TextView> <CheckBox android:id="@+id/itemrowcb" android:layout_width="wrap_content" android:paddingRight="5dip" android:layout_alignParentRight="true" android:focusableInTouchMode="true" android:focusable="false" android:layout_height="wrap_content"></CheckBox> </RelativeLayout> |
.
.
说明
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。
截图与资源
本文参加