Adapter本身只是一个接口,它派生了ListAdapter和SpinnerAdapter两个子接口。

Adapter常用的实现类如下:
–ArrayAdapter:简单、易用的Adapter,通常用于将数组或List集合的多个值包装成多个列表项。
–SimpleAdapter:不简单、功能强大的Adapter,可用于将List集合的多个对象包装成多个列表项。
–SimpleCursorAdapter:与SimpleAdapter基本相似,只是用于包装Cursor提供的数据。
–BaseAdapter:通常用于被扩展。扩展BaseAdapter可以对各列表项进行最大限度的定制。

通过实例介绍

使用ArrayAdapter创建ListView

//此布局文件定义了两个ListView,但这两个ListView都没有指定android:entries属性,这意味着都需要通过Adapter来提供列表项
 <!--设置使用红色的分隔条-->
    <ListView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/list1"
        android:divider="#f00"
        android:dividerHeight="2px"
        android:headerDividersEnabled="false"/>
    <!--设置使用绿色的分隔条-->
    <ListView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/list2"
        android:divider="#0f0"
        android:dividerHeight="2px"
        android:headerDividersEnabled="false"/>

Activity提供Adapter,Adapter决定ListView所显示的列表项

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ListView list1 = (ListView) findViewById(R.id.list1);
        //定义一个数组
        String[] arr1 = {"孙悟空", "牛魔王", "至尊宝"};
        //将数组包装为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 = {"eclipse", "android studio", "vs2013"};
        //将数组包装为ArrayAdapter
        ArrayAdapter<String> adapter2 = new ArrayAdapter<String>(this, R.layout.checked_item, arr2);
        //为ListView设置Adapter
        list2.setAdapter(adapter2);
       }
}

创建ArrayAdapter时必须指定以下三个参数:
–Context:代表访问整个Android应用的接口。几乎创建所有组件都需要传入Context对象。如上面代码使用this。
–textViewResourceld:资源ID,该资源代表一个TextView,该TextView组件将作为ArrayAdapter的列表项组件。
–数组或list:该数组或List兼顾则为多个列表项提供数据。

从上面不难看出,创建ArrayAdapter时传入的第二个参数控制每个列表项的组件,第三个参数则负责为列表提供数据。该数组或List包含多少个元素,就将生成多少个列表项,每个列表项都是TextView组件,TextView组件显示的文本由数组或List的元素提供。

每个列表项的组件外观由下面布局文件控制:

<?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:textColor="#f0f"
    android:shadowDx="4"
    android:shadowDy="4"
    android:shadowRadius="2">

</TextView>

基于ListActivity实现列表

如果程序的窗口仅仅需要显示一个列表,则可以直接让Activity继承ListActivity来实现,ListActivity的子类无须调用setContentView()方法来显示某个界面,而是可以直接传入一个内容Adapter,ListActivity的子类就呈现出一个列表。

public class TwoActivity extends ListActivity {

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //无需布局文件
        String[] arr = {"丁一", "王二", "张三", "李四"};
        //创建ArrayAdapter对象
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
                android.R.layout.simple_list_item_multiple_choice, arr);
        //设置该窗口显示列表
        setListAdapter(adapter);

        //用setchoicemode方法将选择方式设置为CHOICE_MODE_MULTIPLE,即可实现多选的选中效果。
        final ListView listView = getListView();
        listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
    }
}

使用SimpleAdapter创建ListView

ArrayAdapter虽然简单、易用,但ArrayAdapter的功能比较有限,它的每个列表项只能是TextView。如果需要实现更复杂的列表项,则可以使用SimpleAdapter。

界面布局文件:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <!--定义一个ListView-->
    <ListView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/list3"/>
</LinearLayout>

每个列表项的界面布局:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <!--定义一个ImageView,用于作为列表项的一部分-->
    <ImageView
        android:id="@+id/header"
        android:layout_width="80dp"
        android:layout_height="80dp"
        android:paddingLeft="10dp"
        android:scaleType="fitCenter"/>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">
        <!--定义一个TextView,用于作为列表项的一部分-->
        <TextView
            android:id="@+id/name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="40dp"
            android:textColor="#742974"
            android:paddingLeft="10dp"/>
        <!--定义一个TextView,用于作为列表项的一部分-->
        <TextView
            android:id="@+id/desc"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textSize="20dp"
            android:paddingLeft="10dp"
            android:singleLine="true"
            android:ellipsize="end"/>
    </LinearLayout>

</LinearLayout>

Activity代码:

public class ThreeActivity extends AppCompatActivity{

    private String[] names = new String[]{
            "哈利", "皮特", "杰瑞", "汤姆", "川普"};
    private String[] descs = new String[]{
            "头上带闪电的天选之人", "被蜘蛛咬的天选之人",
            "一只脱离了低级趣味的老鼠", "一只奋斗的猫",
            "大美兴,川普王,川普来了不纳粮"
    };
    private int[] imageIds = new int[]{
            R.drawable.hali, R.drawable.zhizhuxia,
            R.drawable.jierui, R.drawable.tangmu,
            R.drawable.chuanpu
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_three);

        //创建一个List集合,List集合的元素是Map
        List<Map<String, Object>> listItems = new ArrayList<Map<String, Object>>();
        for (int i = 0; i < names.length; i++){

            Map<String, Object> listItem = new HashMap<String, Object>();
            listItem.put("header", imageIds[i]);
            listItem.put("personName", names[i]);
            listItem.put("desc", descs[i]);
            listItems.add(listItem);
        }
        //创建一个SimpleAdapter
        SimpleAdapter simpleAdapter = new SimpleAdapter(this,
                listItems, R.layout.simple_item,
                new String[]{"personName", "header", "desc"},
                new int[]{R.id.name, R.id.header, R.id.desc});
        ListView list = (ListView) findViewById(R.id.list3);
        //为ListView设置Adapter
        list.setAdapter(simpleAdapter);

        //为ListView的列表项的单击事件绑定时间监听器
        list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                Toast.makeText(ThreeActivity.this, names[i] + "被单击了",Toast.LENGTH_SHORT).show();
                System.out.println(names[i] + "被单机了");
            }
        });
    }
}

上面代码中还添加了OnItemClickListener单击事件,需要注意的是,OnItemSelectedListener事件可能会无响应,这是因为OnItemSelectedListener是用来监听【选中某一项】的事件,不是【点击】某一项的事件,虽然点击能引发选中事件,但不是必然的, 一般用按键或者鼠标滚轮移动焦点都会产生这个选中事件。


扩展BaseAdapter实现不存储列表项的ListView

扩展BaseAdapter可以取得对Adapter最大的控制权:程序要创建多少个列表项,每个列表项的组件都有开发者决定。

布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ListView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/list4"/>

</LinearLayout>

Activity:

public class FourActivity extends AppCompatActivity{

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_four);

        //获取ListView组件
        ListView list4 = (ListView) findViewById(R.id.list4);
        BaseAdapter adapter = new BaseAdapter() {
            @Override
            public int getCount() {
                //指定一共包含40个选项
                return 40;
            }

            @Override
            public Object getItem(int i) {
                return null;
            }
            //重写该方法,该方法的返回值将作为列表项的ID
            @Override
            public long getItemId(int i) {
                return i;
            }
            //重写该方法,该方法返回的View将作为列表框
            @Override
            public View getView(int i, View view, ViewGroup viewGroup) {
                //创建一个LinearLayout,并向其中添加两个组件
                LinearLayout linearLayout = new LinearLayout(FourActivity.this);
                //设置排列方式
                linearLayout.setOrientation(LinearLayout.HORIZONTAL);
                //图片
                ImageView imageView = new ImageView(FourActivity.this);
                imageView.setImageResource(R.drawable.chuanpu);
                //文本
                TextView textView = new TextView(FourActivity.this);
                textView.setText("第" + (i + 1) + "个列表项");
                textView.setTextSize(20);
                textView.setTextColor(Color.RED);
                linearLayout.addView(imageView);
                linearLayout.addView(textView);
                //返回LinearLayout实例
                return linearLayout;
            }
        };
        list4.setAdapter(adapter);
    }
}

扩展对象需要重写如下4个方法:
–getCount():该方法的返回值控制该Adapter将会包含多少个列表项。
–getItem(int position):该方法的返回值决定第position处的列表项的内容。
–getItemId(int position):该方法的返回值决定第position处的列表项的ID。
–getView(int position, View convertView, ViewGroup parent):该方法的返回值决定第position处的列表项组件。

上述四个方法中最重要的是第一个和第四个。


以上实现Adapter的方法完全适用于AdapterView的其他子类:GridView、、Spinner、Gallery、AdapterViewFlipper等。

总的来说创建步骤就是两步:
1.采用四种方式之一创建Adapter。
2.调用AdapterView的setAdapter(Adapter)方法设置Adapter即可。