![Android Studio移动应用开发从入门到实战(微课版)](https://wfqqreader-1252317822.image.myqcloud.com/cover/529/26793529/b_26793529.jpg)
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属性
![](https://epubservercos.yuewen.com/36329C/15253384904105406/epubprivate/OEBPS/Images/Figure-T42_11242.jpg?sign=1739280486-LUIfHhNFUNMXpUCfksv2Onx9Czr2VfMw-0-03aef07f78d8ace74b9bb0a14a3f8578)
下面将通过一个基于数组的ListView实例来讲解ListView的使用,先看运行图,如图2-18所示。
![](https://epubservercos.yuewen.com/36329C/15253384904105406/epubprivate/OEBPS/Images/Figure-P42_4013.jpg?sign=1739280486-4clsgPEjbwDbFnE09sLZWszWvGDjgX20-0-dbe78cc8cb808653d697e23c52e810c3)
图2-18 ListView组件
要实现上面的界面,首先需要在布局文件中添加ListView组件,然后在values文件夹下添加一个新的arrays.xml文件用来存储数组元素,在ListView组件中通过android:entries调用,把数组元素加载到listview中。具体的实现代码如下:
· 布局文件代码:
![](https://epubservercos.yuewen.com/36329C/15253384904105406/epubprivate/OEBPS/Images/Figure-P42_11243.jpg?sign=1739280486-zXKqxSv8u2IeFXKH0bt4VvoT5mliHWtB-0-51708a39ec1ec03bb11d257f1089b4b8)
· Values下的arrays.xml文件代码:
![](https://epubservercos.yuewen.com/36329C/15253384904105406/epubprivate/OEBPS/Images/Figure-P43_11247.jpg?sign=1739280486-vNTu08Pp8MOm0CtLOKN69knPe53L9u3H-0-dec8592738178c8a8df2774f486c7259)
使用数组创建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代码:
![](https://epubservercos.yuewen.com/36329C/15253384904105406/epubprivate/OEBPS/Images/Figure-P44_11252.jpg?sign=1739280486-l8Npkp5dZbkXJ3LK3S3Hpem7fpWTEJ1C-0-f82fd250b903c4c9dc672bda4be49d26)
实现效果如图2-19所示。
从上面加粗的代码中可以看到创建了一个ArrayAdapter,创建ArrayAdapter时必须要指定3个参数,分别为Context、textViewResourceId、数组或List。第一个参数代表了访问整个Android应用的接口;第二个参数表示一个资源ID,该资源ID代表一个TextView,负责设置列表项的样式,可以自定义;第三个参数代表加入到列表项的元素。
![](https://epubservercos.yuewen.com/36329C/15253384904105406/epubprivate/OEBPS/Images/Figure-P44_4163.jpg?sign=1739280486-H1ruN3BawY2YbAiqswbPy49VqiaQe0nG-0-fb53876a937ff97bdbd099905c7476ae)
图2-19 基于ArrayAdapter实现
实例二:基于SimpleAdapter创建ListView
使用ArrayAdapter实现Adapter虽然比较简单,但是只能实现比较单一的列表,即每个列表项只能是TextView,如果开发者考虑在每一行放置不同的组件,则可以考虑使用SimpleAdapter,下面将通过一个实例讲解SimpleAdapter的使用。
· 主布局界面代码同基于数组创建ListView的布局代码一样。
· 使用SimpleAdapter,需要在layout目录下添加一个自定义的布局文件list_item_layout.xml,即是每一行的布局样式,代码如下:
![](https://epubservercos.yuewen.com/36329C/15253384904105406/epubprivate/OEBPS/Images/Figure-P44_11255.jpg?sign=1739280486-QtUjEiA7BtjHjboS7FFXn8PSIXBCvxTP-0-aa8e6d39a3b026b1f4005221f27c55b5)
· Activity代码如下:
![](https://epubservercos.yuewen.com/36329C/15253384904105406/epubprivate/OEBPS/Images/Figure-P45_11257.jpg?sign=1739280486-HwaNlxgPFAj0VEQbQLrq1V7Eo7QQTgZE-0-ca539d6d6af9ba9c281417dbaa9490ff)
以上程序实现的效果如图2-20所示。
上面程序中加粗的代码是使用SimpleAdapter的重要一步,使用SimpleAdapter最重要的是它的5个参数,尤其是后面4个,接下来就讲一下这4个参数。首先第二个参数是List<?Extends Map<String,?>>类型的集合对象,该集合中每个Map<String,?>对象生成一行;第三个参数是指定一个界面布局的ID,这里引用了一个自定义的布局list_item_layout.xml文件;第四个参数是String[]类型的参数,该参数决定提取哪些内容显示在listview的每一行;最后一个是int[]类型的参数,决定显示哪些组件。
![](https://epubservercos.yuewen.com/36329C/15253384904105406/epubprivate/OEBPS/Images/Figure-P46_4295.jpg?sign=1739280486-aboHNjn5IB8XSjazJBxO3HtRDJEOaMVq-0-afc4ee5816564ac3b79cac95df645988)
图2-20 基于SimpleAdapter实现
实例三:基于BaseAdapter创建ListView
在使用SimpleAdapter时,用户可以在布局中定义按钮,但是当用户单击时,由于单击操作被ListView的Item所覆盖,导致按钮无法获取到焦点,这时候最方便的方法就是使用灵活的适配器BaseAdapter了。
BaseAdapter是最基础的Adapter,也就是说,它可以做所有的事情。说它最实用、最常用,原因就在于它的全能性,它不会像ArrayAdapter等封装好的类有那么多局限性,但是这样的话,使用起来自然会更加麻烦。
使用BaseAdapter可以新建一个Java文件MyBaseAdapter,继承自BaseAdapter,并且重写它的4个基础方法。代码如下所示:
![](https://epubservercos.yuewen.com/36329C/15253384904105406/epubprivate/OEBPS/Images/Figure-P46_11261.jpg?sign=1739280486-Zj3JwuhvsdmEIkVoYnP2oisU7uIKTJgq-0-bd2bf363349f7bb7c06ac2dc3606a96a)
学会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控件。具体如下所示:
![](https://epubservercos.yuewen.com/36329C/15253384904105406/epubprivate/OEBPS/Images/Figure-P47_11265.jpg?sign=1739280486-0Hopzemp3QVCDsqTJI5gEWXTqIHRdQQe-0-aea9c8b77a6427149ab58a037e2fd11a)
使用BaseAdapter与SimpleAdapter类似,都需要在layout目录下添加一个自定义的布局文件list_item_layout.xml(即每一行的布局样式)。代码如下:
![](https://epubservercos.yuewen.com/36329C/15253384904105406/epubprivate/OEBPS/Images/Figure-P47_11266.jpg?sign=1739280486-krqxZuC8l4AZtlD1gqlGWmKTgPkrCWfk-0-cc2c8fd2b35006ea91f8f6ddbeffb981)
接着就是最重要的一步,即自定义一个MyAdapter类继承自BaseAdapter,然后重写其中的方法。具体的代码如下所示:
![](https://epubservercos.yuewen.com/36329C/15253384904105406/epubprivate/OEBPS/Images/Figure-P48_11268.jpg?sign=1739280486-bO3Hhr48vAP6dc6DcfrxApgrhtanRBcM-0-eeedff3d62f46b59af5d025936ec76a4)
![](https://epubservercos.yuewen.com/36329C/15253384904105406/epubprivate/OEBPS/Images/Figure-P49_11269.jpg?sign=1739280486-gmFgCuxF1u22hpHOJ6tETxaAsFGidv7h-0-ac0304f54c84de780ccd37a44912bfde)
最后就是在MainActivity中添加数据以及为ListView添加上文自定义的Adapter。具体的代码如下所示:
![](https://epubservercos.yuewen.com/36329C/15253384904105406/epubprivate/OEBPS/Images/Figure-P50_11270.jpg?sign=1739280486-iNQQRn7sKQLXk8etjWg4DVrm7dSkX1Gz-0-ee38b5bc46326eda8850097646cfb2a8)
运行程序,单击界面上的自定义按钮,实现的效果如图2-21所示。
![](https://epubservercos.yuewen.com/36329C/15253384904105406/epubprivate/OEBPS/Images/Figure-P51_4510.jpg?sign=1739280486-itnKtOzs8mNggsPjVwfNb7Ed6sSWtNLH-0-2aed375a01b2e0123d4ecdfba91d766d)
图2-21 基于BaseAdapter实现