2.4 AdapterView及其子类

AdapterView是一种重要的组件,AdapterView本身是一个抽象基类,它派生的子类在用法上十分相似,只是显示界面上有一定的区别。AdapterView具有如下特征:

· AdapterView继承了ViewGroup,它的本质是容器。

· AdapterView可以包括多个“列表项”,并以合适的方式显示出来。

· AdapterView显示的多个“列表项”由Adapt提供。调用AdapterView的setAdapter(Adapter)方法设置Adapter即可。

2.4.1 ListView和ListActivity

ListView是手机系统中使用非常广泛的一种组件,它以垂直列表的形式显示所有的列表项。生成列表视图有如下两种方式:

· 直接使用ListView进行创建。

· 创建一个继承ListActivity的Activity(相当于该Activity显示的组件为ListView)。

一旦在程序中获得了ListView之后,接下来就需要为ListView设置它要显示的列表项了。在这一点上,ListView显示出了AdapterView的特征:通过setAdapter(Adapter)方法为之提供Adapter,并由Adapter提供列表项即可。

ListView提供的常用的XML属性如表2-5所示。

表2-5 ListView常用的XML属性

下面将通过一个基于数组的ListView实例来讲解ListView的使用,先看运行图,如图2-18所示。

图2-18 ListView组件

要实现上面的界面,首先需要在布局文件中添加ListView组件,然后在values文件夹下添加一个新的arrays.xml文件用来存储数组元素,在ListView组件中通过android:entries调用,把数组元素加载到listview中。具体的实现代码如下:

· 布局文件代码:

· Values下的arrays.xml文件代码:

使用数组创建ListView是一种非常简单的方式,但是这种ListView能定制的内容很少,如果想对ListView的外观、行为等进行自定义,就需要把ListView作为AdapterView使用,通过Adapter自定义每个列表项的外观、内容以及添加的动作行为等。

2.4.2 Adapter接口

Adapter本身只是一个接口,它派生了ListAdapter和SpinnerAdapter两个子接口,其中ListAdapter为AbsListView提供列表项,而SpinnerAdapter为AbsSpinner提供列表项。

Adapter常用的实现类如下所示:

· BaseAdapter——一个抽象类,继承它需要实现较多的方法,所以也就具有较高的灵活性。

· ArrayAdapter——支持泛型操作,最为简单,只能展示一行字。

· SimpleAdapter——有最好的扩充性,可以自定义各种效果。

下面将通过具体的实例讲解常用的Adapter实现类的用法。

实例一:基于ArrayApter创建ListView

· 布局界面代码同基于数组创建ListView的布局代码一样。

· Activity代码:

实现效果如图2-19所示。

从上面加粗的代码中可以看到创建了一个ArrayAdapter,创建ArrayAdapter时必须要指定3个参数,分别为Context、textViewResourceId、数组或List。第一个参数代表了访问整个Android应用的接口;第二个参数表示一个资源ID,该资源ID代表一个TextView,负责设置列表项的样式,可以自定义;第三个参数代表加入到列表项的元素。

图2-19 基于ArrayAdapter实现

实例二:基于SimpleAdapter创建ListView

使用ArrayAdapter实现Adapter虽然比较简单,但是只能实现比较单一的列表,即每个列表项只能是TextView,如果开发者考虑在每一行放置不同的组件,则可以考虑使用SimpleAdapter,下面将通过一个实例讲解SimpleAdapter的使用。

· 主布局界面代码同基于数组创建ListView的布局代码一样。

· 使用SimpleAdapter,需要在layout目录下添加一个自定义的布局文件list_item_layout.xml,即是每一行的布局样式,代码如下:

· Activity代码如下:

以上程序实现的效果如图2-20所示。

上面程序中加粗的代码是使用SimpleAdapter的重要一步,使用SimpleAdapter最重要的是它的5个参数,尤其是后面4个,接下来就讲一下这4个参数。首先第二个参数是List<?Extends Map<String,?>>类型的集合对象,该集合中每个Map<String,?>对象生成一行;第三个参数是指定一个界面布局的ID,这里引用了一个自定义的布局list_item_layout.xml文件;第四个参数是String[]类型的参数,该参数决定提取哪些内容显示在listview的每一行;最后一个是int[]类型的参数,决定显示哪些组件。

图2-20 基于SimpleAdapter实现

实例三:基于BaseAdapter创建ListView

在使用SimpleAdapter时,用户可以在布局中定义按钮,但是当用户单击时,由于单击操作被ListView的Item所覆盖,导致按钮无法获取到焦点,这时候最方便的方法就是使用灵活的适配器BaseAdapter了。

BaseAdapter是最基础的Adapter,也就是说,它可以做所有的事情。说它最实用、最常用,原因就在于它的全能性,它不会像ArrayAdapter等封装好的类有那么多局限性,但是这样的话,使用起来自然会更加麻烦。

使用BaseAdapter可以新建一个Java文件MyBaseAdapter,继承自BaseAdapter,并且重写它的4个基础方法。代码如下所示:

学会BaseAdapter其实只需要掌握4个方法:getCount、getItem、getItemId、getView。每个方法的具体含义如下所示:

· getCount——要绑定的条目的数目,比如格子的数量。

· getItem——根据一个索引(位置)获得该位置的对象。

· getItemId——获取条目的id。

· getView——获取该条目要显示的界面。

可以理解为adapter先由getCount确定数量,然后循环执行getView方法将条目一个一个绘制出来,所以必须重写的是getCount和getView方法。而getItem和getItemId是调用某些函数才会触发的方法,如果不需要使用可以暂时不修改。接下来将通过具体的例子来讲解BaseAdapter的使用。

首先创建chapter3_BaseAdapter项目,修改activity_main.xml的代码,添加一个ListView控件。具体如下所示:

使用BaseAdapter与SimpleAdapter类似,都需要在layout目录下添加一个自定义的布局文件list_item_layout.xml(即每一行的布局样式)。代码如下:

接着就是最重要的一步,即自定义一个MyAdapter类继承自BaseAdapter,然后重写其中的方法。具体的代码如下所示:

最后就是在MainActivity中添加数据以及为ListView添加上文自定义的Adapter。具体的代码如下所示:

运行程序,单击界面上的自定义按钮,实现的效果如图2-21所示。

图2-21 基于BaseAdapter实现