前一天学习了AutoCompleteTextView控件的使用方法。该控件主要的功能是根据用户部分输入,显示完整信息列表,供用户选择。AutoCompleteTextView控件与显示信息的关联是通过集合适配器实现的。集合适配器是一个泛型适配器,通过ArrayAdapter类的构造函数定义集合适配器,通过AutoCompleteTextView类的setAdapter()方法设置控件的适配器。
今天我们学习ListView控件。ListView控件是安卓系统编程中常用的控件,几乎所有的应用程序都会用到。由于手机屏幕空间有限,能够一次性在屏幕上显示的内容并不多,当程序中有大量的数据需要显示时,可以借助ListView来实现。用户可以通过滑动屏幕的方式进行数据的切换。在查看手机通信录或则浏览新闻网站时,都会用到该控件。
今天要实现程序的功能是使用ListView控件显示图像和文字,如图1所示。
图1 ListView控件显示图片和文字
在“AutoCompleteTextView控件”的学习当中提到,集合适配器(ArrayAdapter)是数据与控件的桥梁。在ListView控件中显示图片和文字也要用到ArrayAdapter,并且是自定义类的ArrayAdapter。
1 自定义类
在MainActivity类的内部自定义一个名叫“Continent”的类,作为ArrayAdapter中的元素。该类包含了洲的名称和洲对应的图片ID两个变量。并为该类定义两个公共的方法来获取这两个变量。
1 publicclass Continent {
2 private Stringname;
3 privateintimageId;
4 public Continent(String name,int imageId){
5 this.name = name;
6 this.imageId = imageId;
7 }
8 public String getName(){
9 returnname;
10 }
11 publicint getImageId()
12 {
13 returnimageId;
14 }
15 }
其中,2-3行声明了两个变量,name表示洲名,imageId表示图片ID;4-7行定义了Continent的构造函数;8-14定义了两个函数用来获取洲名和图片ID。
2 自定义ArrayAdapter
接下来定义泛型为Continent的ArrayAdapter。
publicclass ContinentAdapterextends ArrayAdapter<Continent>{
........
}
2.1构造函数的定义
自定义的类ContinentAdapter派生自ArrayAdapter。ArrayAdapter类有一种构造函数的格式是
ArrayAdapter(Context context,int resource, List<T>objects)
其中,context表示当前的上下文;resource表示包含TextView等控件的构造文件的ID;objects表示ListView控件中表示的对象,泛型即为对象的类型。
因此,在自定义类ContinentAdapter中定义其构造函数,代码如下:
1 privateintresourceId;
2 public ContinentAdapter(Context context,int textViewResourceId,
3 List<Continent> objects){
4 super(context, textViewResourceId, objects);
5 resourceId =textViewResourceId;
6 }
以上代码的含义如图2-1所示。
图2-1 代码含义
ListView中每个子项的布局文件都是textViewResourceId指定的界面布局xml文件,而每个子项要表示的数据即为自定义的Continent类。
2.2getView方法的重载
对于自定义的ArrayAdapter,要实现除TextView之外的其他功能,例如通过ImageView显示控件等,则要重载getView()方法。getView()方法的作用是获取并显示视图,该视图用来显示在指定位置的数据,当ListView中的子项在屏幕上显示时,就会调用该方法。
重载该方法的目的是在ListView的子项中导入布局文件,并且显示该子项表示的数据中的图像和文字。
getView()方法的格式为
public View getView (intposition, View convertView, ViewGroup parent)
其中,position表示要获取的视图在适配器中的位置;convertView表示可以重复使用的视图;parent表示与视图关联的父视图。重载getView()方法的代码为
@Override
public View getView(int position,View convertView, ViewGroup parent){
.......
}
2.2.1 适配器数据的获取
在重载的getView()方法中,首先通过ArrayAdapter类的getItem方法获取指适配器中指定位置的数据。
Continent continent= getItem(position);
其中,Continent是适配器中的数据,position是getView()方法的第一个参数。要获取的视图对应的数据即为continent。
2.2.2 布局视图的获取
ListView中的每一个子项都是由TextView控件和ImageView控件组成的,其中TextView控件用来显示文字而ImageView控件用来显示图像。因此,在ListView的每个子项显示时都要导入这种布局。
View view = LayoutInflater.from(getContext()).inflate(resourceId,null);
其中,LayoutInflater类是android.view类中定义的子类,该类的主要作用是将布局XML文件实例化成相应的视图对象。而from()是LayoutInflater类的方法,其格式为
publicstatic LayoutInflater from (Context context)
该方法的作用是根据给定的上下文context获取LayoutInflater。而在源代码中from()方法的参数是getContext()方法,该方法的作用正是获取正在运行程序的上下文。在源代码中,LayoutInflater.from(getContext())正是获取到的LayoutInflater,在通过其调用LayoutInflater类的inflate()方法根据布局XML文件设置视图的布局。该方法的格式之一是
public View inflate (intresource, ViewGroup root)
其中,resource是要导入的XML布局文件的ID,root是一个可选参数,指定了根据XML文件产生的布局的根的视图。在上述的代码中,inflate()方法的第一个参数resourceId是自定义类ArrayAdapter的成员变量,在其构造函数时指定,实际上就是ListView中每个子项对应的XML布局文件;第二个参数null表示inflate()方法的返回值即为该方法根据XML布局文件创建的视图,即变量view。
2.2.3 显示文字及图像
获取了XML布局文件创建的视图之后,获取该视图中的TextView控件和ImageView控件,指定这两个控件显示的内容即可。
1 ImageView continentImage =
2 (ImageView)view.findViewById(R.id.continent_image);
3 TextView continentName =(TextView)view.findViewById(R.id.continent_name);
4 continentImage.setImageResource(continent.getImageId());
5 continentName.setText(continent.getName());
其中,第1-2行获取ImageView控件,continent_image是在XML布局文件中定义的ImageView控件的ID;第3行获取TextView控件,continent_name是TextView控件的ID;第4行通过setImageResource()方法设置ImageView控件显示的图像,该方法的参数中continent是在2.2.1中获取到的要显示的数据,getImageId()是自定义Continent的方法,该方法在1中定义,返回值是指定图像的资源ID;第5行通过setText()方法指定了TextView控件显示的文字,参数中的continent是在2.2.1中获取到的要显示的数据,getName()是自定义Continent的方法,该方法在1中定义,返回值是指定内容。