Adapter接口及实现类
Adapter本身只是一个接口,它派生了ListAdapter和SpinnerAdapter两个子接口,其中ListAdapter为AbsListView提供列表项,而SpinnerAdapter为AbsApinner提供列表项。Adapter接口及其实现关系类图如图所示:
从类图中可以看出Adapter都继承了BaseAdapter,而BaseAdapter同时实现了ListAdapter、SpinnerAdapter两个接口,因此BaseAdapter及其子类可以同时为AbsListView、AbsSpinner提供列表项。
Adapter常用的实现类如下:
- ArrayAdapter:简单、易用的Adapter,通常用于将数组或List集合的多个值包装成多个列表项。
- SimpleAdapter:并不简单、功能强大的Adapter,可用于将List集合的多个对象包装成多个列表项。
- SimpleCursorAdapter:与SimpleAdapter基本相似,只是用于包装Cursor提供的数据。
- BaseAdapter:通常用于被扩展。扩展BaseAdapter可以对各列表项进行最大限度的定制。
实例:使用ArrayAdapter创建ListView
下面的实例在界面布局文件中定义了两个ListView
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <!-- 设置红色的分隔条 --> <ListView android:id="@+id/list1" android:layout_width="fill_parent" android:layout_height="wrap_content" android:divider="#f00" android:dividerHeight="2px" android:headerDividersEnabled="false"></ListView> <ListView android:id="@+id/list2" android:layout_width="fill_parent" android:layout_height="wrap_content" android:divider="#0f0" android:dividerHeight="2px" android:headerDividersEnabled="false"></ListView> </LinearLayout>
上面的布局文件定义了两个ListView,但这两个ListView都没有指定android:entries属性,这意味着它们都需要通过Adapter来提供列表项。
接下来Activity为两个ListView提供Adapter,Adapter决定ListView所显示的列表项。程序如下:
package org.crazyit.helloworld; import android.os.Bundle; import android.app.Activity; import android.view.Menu; import android.widget.*; public class ListViewTest2 extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.list_view_test2); ListView list1=(ListView)findViewById(R.id.list1); //定义一个数组 String[] arr1=new String[]{"孙悟空","猪八戒","牛魔王"}; //将数组包装为ArrayAdapter ArrayAdapter<String> adapter1=new ArrayAdapter<String>(this,R.layout.array_item,arr1); //为ListView设置Adapter list1.setAdapter(adapter1); ListView list2=(ListView)findViewById(R.id.list2); //定义一个数组 String[] arr2=new String[]{"Java","Hibernate","Spring","Android"}; //将数组包装为ArrayAdapter ArrayAdapter<String> adapter2=new ArrayAdapter<String>(this,R.layout.checked_item,arr2); //为ListView设置Adapter list2.setAdapter(adapter2); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.list_view_test2, menu); return true; } }
上面的程序中两行粗体字代码创建了两个ArrayAdapter,创建ArrayAdapter时必须指定如下三个参数。
- Context:这个参数无须多说,它代表了访问整个Android应用的接口。几乎创建所有组件都需要传入Context对象。
- textViewResourceId:一个资源ID,该资源ID代表一个TextView,该TextView组件将作为ArrayAdapter的列表项组件。
- 数组或List:该数组或List将负责为多个列表项提供数据。
从上面的介绍不难看出,创建ArrayAdapter时传入的第二个参数控制每个列表项的组件,第三个参数负责为列表项提供数据。该数组或List包含多少个元素,将生成多少个列表项,每个列表项都是TextView组件,TextView组件显示的文本由数组或List的元素提供。
以上面的代码中第一个ArrayAdapter为例,该ArrayAdapter对应的数组为{“孙悟空”,"猪八戒","牛魔王"},该数组将会负责生成一个包含三个列表项的ArrayAdapter,每个列表项的组件外观有R.layout.array_item布局文件(该布局文件只是一个TextView组件)控制,第一个TextView列表项显示的文本为“孙悟空”,第二个TextView列表项显示的文本为“猪八戒”......
R.layout.array_item布局文件如下:
<?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/TextView" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="24dp" android:padding="10px" android:shadowColor="#f0f" android:shadowDx="4" android:shadowDy="4" android:shadowRadius="2" > </TextView>
R.layout.checked_item布局文件如下:
<?xml version="1.0" encoding="utf-8"?> <CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/TextView" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="24dp" android:checkMark="@drawable/ok" android:shadowColor="#f0f" android:shadowDx="4" android:shadowDy="4" android:shadowRadius="2" > </CheckedTextView>
运行上面的代码出现下图效果: