ListView是Android软件开发中十分常用也十分重要的一个UI控件。ListView的每一个子项可以是一个简单的字符串,也可以是一组View的组合,开发者完全可以根据自己的需求来定义显示的形式。
如何使用一个ListView实现对数据的显示呢?
1. 创建ListView控件,已备数据显示
2. 准备要显示的数据
3. 为ListView构建一个数据适配器(Adapter)
4. 绑定适配器
5. 处理ListView操作回调,完成业务功能
如何创建ListView?
我们可以直接使用xml格式的布局(layout)文件来创建一个ListView,如果我们已经有一个布局(layout)文件,直接添加ListView控件。
然后再Activity中去获取该控件,这样就可以使用该控件了。
当然,我们也可以直接用代码创建一个ListView控件,并把该控件作为要显示的View,或者添加到现有的一个groupview控件中去。
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
ListView myListView = new ListView(this);
setContentView(myListView);
}
一般建议在布局(layout)文件中进行UI控件的定义。
如何创建一个适配器?
在这几个步骤中,构建数据适配器是很重要的一个环节,同样也是比较复杂的一个环节。ListView常用的适配器(Adapter)有以下几种。
Adapter |
含义 |
ArrayAdapter |
用来绑定一个数组,支持泛型操作 |
SimpleAdapter |
用来绑定在xml中定义的控件对应的数据 |
SimpleCursorAdapter |
用来绑定游标得到的数据 |
BaseAdapter |
通用的基础适配器 |
1. 准备数据
private static final String[] strDatas = new String[] {
"first", "second", "third", "fourth", "fifth"
};
2. 直接绑定
ListView lv = (ListView) findViewById(R.id.id_listview_list);
lv.setAdapter(new ArrayAdapter(this,
android.R.layout.simple_list_item_1, strDatas));
此处使用了Android系统自带的一个列表Item样式,显示效果如下图:
使用ArrayAdapter绑定数据适用数据特别简单的情况。
1.创建列表Item样式布局文件(simple_adapter_item.xml)
2.准备数据
List
3.绑定适配器
ListView lv = (ListView) findViewById(R.id.id_listview_list);
lv.setAdapter(new SimpleAdapter(this,
data, R.layout.simple_adapter_item,
new String[]{"id","name","phone"},
new int[]{R.id.sai_id,R.id.sai_name, R.id.sai_phone}));
显示效果如下:
1.此示例中列表Item样式布局文件直接复用上个例子中的布局文件simple_adapter_item.xml。
2.准备数据
一般情况下Cursor都是通过查找数据获取到的,此处我们的重点是看如何用在SimpleCursorAdapter中来绑定到ListView中,因此我们使用可以直接示例化并可以直接插入数据的MatrixCursor类完成数据提供任务。代码如下:
String[] tableCursor = new String[] { "_id", "name", "phone" };
MatrixCursor cursor = new MatrixCursor(tableCursor);
cursor.addRow(new Object[]{"100", "张大", "13588551201" });
cursor.addRow(new Object[]{"101", "张二", "13588551202" });
cursor.addRow(new Object[]{"102", "张三", "13588551203" });
cursor.addRow(new Object[]{"103", "张四", "13588551204" });
cursor.addRow(new Object[]{"104", "张五", "13588551205" });
与上一个例子的数据几乎一样,有没有发现,此处简单了很多呢?哈哈!不过需要注意的是,作为SimpleCursorAdapter的Cursor必需要有"_id"列,否则会报错。
3.数据绑定
ListView lv = (ListView)findViewById(R.id.id_simplecursordapter_list);
lv.setAdapter(new SimpleCursorAdapter(this,
R.layout.simple_adapter_item, cursor, tableCursor, new int[]{R.id.sai_id,R.id.sai_name, R.id.sai_phone}));
运行效果如下,是不是和上面一个例子效果一样啊!
OK, 此处其实才是ListView用的最多的适配器实现方式,一般都是通过继承BaseAdapter类并重写父类的一些方法来完成ListView数据的绑定。继承BaseAdapter的类必需实现以下几个接口函数:
public int getCount(); //获取适配器中数据集中数据的条目数
public Object getItem(int i);//获取数据集中与指定索引对应的数据项
public long getItemId(int i);//获取数据集中指定索引对应的项的id
public View getView(int i, View view, ViewGroup viewGroup);//获取指定索引的列表Item的view
下面,还是使用与上面两个例子相同的列表布局及类似数据来实现列表的数据绑定实现。
1.建立数据类
public class Data {
public Data(String i, String n, String p){
id = i;
name = n;
phone = p;
}
public String id;
public String name;
public String phone;
}
2.继承BaseAdapter实现我们自己的适配器
public class MyAdapter extends BaseAdapter {
private List mDatas = null;
private Context mContext = null;
public MyAdapter(Context context, List datas){
mDatas = datas;
mContext = context;
}
@Override
public int getCount() {
return mDatas.size();
}
@Override
public Object getItem(int i) {
return mDatas.get(i);
}
@Override
public long getItemId(int i) {
return i;
}
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
ViewHolder vh;
if (view == null){
vh = new ViewHolder();
view = LayoutInflater.from(mContext).inflate(R.layout.simple_adapter_item, null);
vh.id = (TextView)view.findViewById(R.id.sai_id);
vh.name = (TextView)view.findViewById(R.id.sai_name);
vh.phone = (TextView)view.findViewById(R.id.sai_phone);
view.setTag(vh);
} else {
vh = (ViewHolder)view.getTag();
}
vh.id.setText(mDatas.get(i).id);
vh.name.setText(mDatas.get(i).name);
vh.phone.setText(mDatas.get(i).phone);
return view;
}
public final class ViewHolder
{
public TextView id;
public TextView name;
public TextView phone;
}
}
适配其中使用了ViewHolder来提升ListView的绘制效率,通过使用ViewHolder,ListView的Item就可以复用View,而不用每次都去新建一个View。关于此方面知识,可以参考相关文章,此处的示例代码采用比较常用的实现方式,目的也是让大家从一开始认识他的时候就建立几个好的初印象,避免误导了读者。
3.准备数据并绑定到ListView
List datas = new ArrayList();
Data data1 = new Data("111", "老周1", "13656461200");
Data data2 = new Data("112", "老周2", "13656461201");
Data data3 = new Data("113", "老周3", "13656461202");
Data data4 = new Data("114", "老周4", "13656461203");
Data data5 = new Data("115", "老周5", "13656461204");
Data data6 = new Data("116", "老周6", "13656461205");
datas.add(data1);
datas.add(data2);
datas.add(data3);
datas.add(data4);
datas.add(data5);
datas.add(data6);MyAdapter adapter = new MyAdapter(this, datas);
ListView lv = (ListView)findViewById(R.id.id_baseadapter_list);
lv.setAdapter(adapter);
此处数据的获取略显笨拙,但在实际的项目中,一般都是从数据库获取数据,或者是像文件浏览器直接获取系统文件信息。
显示效果还是与上面类似的鸟样:
OK,上面介绍了四种ListView的Adapter来实现ListView的数据绑定,我们来做一个简单的比较。
ArrayAdapter
SimpleAdapter 可以自定义Item布局,用于显示交简单的布局及控件,但布局内的控件如按钮等无法获取到焦点,当然也就无法获取到他们的点击事件。
SimpleCursorAdapter 与SimpleAdapter相似,只是他的数据源是Cursor类型而已。
BaseAdpter子类 最常用的ListView数据适配器,通过继承BaseAdpter可以较灵活的实现数据的绑定,同时通过使用ViewHolder等技术可以很好的提高ListView的绘制效率。另一个很重要的原因,BaseAdpter类适配器绑定的Item布局中的子控件可以获取到触摸焦点,也就是说,通过这种方式,我们可以获取Item布局中一些对象的点击,长按,check等方法。