不论是Android开发还是其他方面的开发,我认为列表都是非常常用的一种控件,现在是一个信息时代,更是一个数据时代,庞大的数据和频繁更新的数据人工一条条输入是一件很费力的工作。
ListView作为Android中的列表控件同样十分重要,Android为它配备的功能和实现方法也非常多样和强大。
在学ListView前看到过很多关于ListView的描述,论使用,一开始就引入适配器,当然最常用的方法都要借助适配器(Adapter,ListView继承自AdapterView),如其他一些控件一样,ListView是可以光通过Xml布局文件来实现的。
首先ListView控件有以下属性:
entries:设置显示数组数据
divider:设置每项的分割条背景
dividerHeight:设置分割条的高度
entries属性值为引用数据,所要显示的内容就写在这里,引用的文件必须新建在res/values目录下,并且文件名必须为arrays.xml,根元素必须为resources,通过写入string-array元素来为列表准备数据,arrays.xml文件如下

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array name="character">
        <item >盖伦</item>
        <item >锐文</item>
        <item >亚索</item>
        <item >伊泽瑞尔</item>
        <item >德莱厄斯</item>
        <item >泽拉斯</item>
    </string-array>
</resources>

在布局文件中简单设置如下,这里并没有为每一项设置布局,它会使用一种默认,其中值包含一个TextView


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#000000" >

    <ListView
        android:entries="@array/character"
        android:divider="#ff0000"
        android:background="#ffffff"
        android:dividerHeight="2.5dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        />

</RelativeLayout>

效果如下


android的和listvie冲突 android listview adapter_android的和listvie冲突


这种方式虽然简单易行,但是它只能是一个死的列表,数据无法更新,而且每个列表项的格式固定亦无法更改,适配器存在的作用就是不通过人工输入数据,由适配器将数据以一定的格式填入到ListView的每项中。


适配器是一种典型的MVC(模型-视图-控制)设计模式,通过适配器连接数据和AdapterView,能够有效地实现数据与AdapterView的分离设置,使整个创建和操作过程更简便,自定义的空间越大。


常见的Adapter有:


ArrayAdapter:通常用于将数组或List集合的多个值包装成多个列表项,只能使用Android自带的布局


SimpleAdapter:可以用于将List集合的多个对象包装成多个列表项,可以使用自定义布局(可以有文字、图片等)


SimpleCursorAdapter:与SimpleAdapter相似,只是用于包装Cursor提供的数据(Cursor数据来源于数据库或网络)


BaseAdapter:可以对各列表项进行最大限度的定制,Adapter的基类,原始就是无解


1)ArrayAdapter


创建adapter的同时就要为ListView布置布局和数据,ArrayAdapter需要使用Android自带的布局:


simple_list_item_1:每项显示一个内容(1个TextView)


simple_list_item_2:每项显示两个内容(2个TextView,垂直排列)


simple_list_item_single_choice:带有单选框的布局形式


simple_list_item_multiple_choice:带有多选框的布局形式


simple_list_item_checked:带有选择框的布局形式


这三个带有按钮的布局并不是设定了这样的控件就表示它就是单选或多选了,还需要额外设定一下方法才能使它们成为真正的单选或多选


setChoiceMode(ListView.CHOICE_MODE_SINGLE);单选框


setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);多选框


setChoiceMode(ListView.CHOICE_MODE_CHECKED);选择框


这些布局都比较单一,可以用来显示较为单一的数据格式。


同时,也可以通过ListView为它的子项添加时间监听


setOnItemClickListener(OnItemClickListener)单击事件


setOnItemLongClickListener(OnItemLongClickListener)长按事件


布局文件如下


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#000000" >

    <ListView
        android:id="@+id/listview"
        android:divider="#ff0000"
        android:background="#ffffff"
        android:dividerHeight="2.5dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        />

</RelativeLayout>

MainAvctivity.class类文件如下


import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;

public class MainActivity extends Activity {
	ListView listview;
	String[] books = {"Java","XML","JDBC","Android","Oracle"};
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		listview = (ListView) findViewById(R.id.listview);
		//适配器参数1为上下文,参数2为单个列表布局格式,参数3为String类型数组
		ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
				android.R.layout.simple_list_item_1, books);
		//加载适配器
		listview.setAdapter(adapter);
		listview.setOnItemClickListener(new OnItemClickListener() {
			@Override
			//参数args2代表列表中第几行,当然从0开始
			public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
					long arg3) {
				Toast.makeText(MainActivity.this, "单击:"+books[arg2], Toast.LENGTH_SHORT).show();
			}
		});
		listview.setOnItemLongClickListener(new OnItemLongClickListener() {
			@Override
			public boolean onItemLongClick(AdapterView<?> arg0, View arg1,
					int arg2, long arg3) {
				Toast.makeText(MainActivity.this, "长按:"+books[arg2], Toast.LENGTH_SHORT).show();
				//返回值如果为false,通过长按出发本是件之后也会触发单击事件
				return true;
			}
		});
	}
}

效果如下

android的和listvie冲突 android listview adapter_listview_02

android的和listvie冲突 android listview adapter_listview_03

2)SimpleAdapter

创建SimpleAdapter的过程比创建ArrayAdapter要复杂,首先ArrayAdapter只需要准备之多两组数据,且均为文本类型,SimpleAdapter的布局是自定义的,自定义布局中有几种数据就要为它布置几种数据,并且要绑定到适配器的数据必须是List<? extends Map<String,?>>类型的,既然有多组数据,那么就要分配数据被分配的位置和控件,这也是Map的key值为字符串类型的原因。

数据填充一般是先为Map添加元素,在把Map加入到List中。这个方式看似复杂其实是一目了然的,看代码体会,一下为ListView中每一项的自定义布局listview.xml,布局大概是左边一个图片,右边一行字体较大的文字和一行字体较小的文字。

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

    <ImageView
        android:id="@+id/iv_icon"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:contentDescription="@android:attr/imageWellStyle"
        android:src="@drawable/ic_launcher" />

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:layout_gravity="center_vertical" >

        <TextView
            android:id="@+id/tv_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="#ff0000"
            android:textSize="20sp" />

        <TextView
            android:id="@+id/tv_detail"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="#0000ff"
            android:textSize="15sp" />
    </LinearLayout>

</LinearLayout>

布局文件如下

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <ListView 
        android:id="@+id/listview"
        android:divider="#ff0000"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    </ListView>

</RelativeLayout>

MainActivity.class类文件如下


import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.app.Activity;
import android.os.Bundle;
import android.widget.ListView;
import android.widget.SimpleAdapter;

public class MainActivity extends Activity {
	ListView listView;
	//图片
	int icons[] = {R.drawable.a1,R.drawable.a2,R.drawable.a3,
			R.drawable.a4,R.drawable.a5,R.drawable.a6,R.drawable.a7};
	//第一行文字
	String[] names = {"AAAA","BBBB","CCCC","DDDD","EEEE","FFFF","GGGG"};
	//第二行文字
	String[] details = {"aaaaaaaa","bbbbbbbb","cccccccc","dddddddd",
			"eeeeeeee","ffffffff","gggggggg"};
	List<Map<String,Object>> list;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		listView = (ListView) findViewById(R.id.listview);
		list = new ArrayList<Map<String,Object>>();
		//数据填充
		for(int i=0;i<icons.length;i++){
			HashMap<String,Object> map = new HashMap<String, Object>();
			map.put("item_icon", icons[i]);
			map.put("item_name", names[i]);
			map.put("item_detail", details[i]);
			list.add(map);
		}
		SimpleAdapter adapter = new SimpleAdapter(
				this,//参数1为上下文 
				list, //参数2为数据,只能是List<? extends Map<String,?>>类型
				R.layout.listview, //参数3为自定义条目的布局
				new String[]{"item_icon","item_name","item_detail"}, //参数4:from,数据名,Map的key值
				new int[]{R.id.iv_icon,R.id.tv_name,R.id.tv_detail});//参数5:to,控件,与数据名对应
		listView.setAdapter(adapter);
	}
}

效果如下

android的和listvie冲突 android listview adapter_listview_04

3)BaseAdapter的使用与SimpleAdapter大同小异,但是BaseAdapter更加强大,将独占一篇博客来写。