代码改变世界

ListView高级用法

2010-12-13 20:38  RayLee  阅读(3574)  评论(0编辑  收藏  举报

ListView基本用法一文介绍了如何操作数据。本文将重点说明如何更丰富的显示这些数据。上文提到,ListAdapter封装了数据的显示,它为ListView和数据本身之间建起了桥梁。查看SDK文档,ListAdapter定义为接口,实现该接口的类有BaseAdapter,ArrayAdapter<T>,SimpleCursorAdapter等等。

ArrayAdapter<T>

ArrayAdapter是最常用的一种适配器。其中的每个数据项最常用的显示布局为android.R.layout.simple_list_item_1。查看源码,你发现它仅仅是一个TextView。

simple_list_item_1.xml

<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/text1"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:textAppearance="?android:attr/textAppearanceLarge"
    android:gravity="center_vertical"
    android:paddingLeft="6dip"
    android:minHeight="?android:attr/listPreferredItemHeight"
/>

 

Android系统同时定义了android.R.layout_simple_list_item_2。

simple_list_item_2.xml

<TwoLineListItem xmlns:android="http://schemas.android.com/apk/res/android" 
	android:paddingTop="2dip"
	android:paddingBottom="2dip"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:minHeight="?android:attr/listPreferredItemHeight"
    android:mode="twoLine"
>
    
	<TextView android:id="@android:id/text1"
		android:layout_width="fill_parent"
		android:layout_height="wrap_content"
        android:layout_marginLeft="6dip"
        android:layout_marginTop="6dip"
		android:textAppearance="?android:attr/textAppearanceLarge"
	/>
		
	<TextView android:id="@android:id/text2"
		android:layout_width="fill_parent"
		android:layout_height="wrap_content"
		android:layout_below="@android:id/text1"
        android:layout_alignLeft="@android:id/text1"
		android:textAppearance="?android:attr/textAppearanceSmall"
	/>

</TwoLineListItem>

那么如何将它和ArrayAdapter结合起来使用?下面用例子说明:

首先定义UI:

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

	<Button android:layout_width="wrap_content"
			android:layout_height="wrap_content"
			android:text="Add"
			android:id="@+id/btnAdd" />
			
	<ListView android:layout_width="fill_parent"
			android:layout_height="fill_parent"
			android:id="@+id/list" />
</LinearLayout>

 

然后是Activity的实现:

public class MainActivity extends Activity {

	String[] items = { "One", "Two", "Three" };

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		ListView list = (ListView) findViewById(R.id.list);
		
		ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
				android.R.layout.simple_list_item_2, android.R.id.text1, items);
		
		list.setAdapter(adapter);
	}
}

得出的效果图:

device

simple_list_item_2还包含一个id为text2的TextView,如何让它也显示数据?上面这种方法似乎无能为力,那么就要通过重写的方式来实现。

例如要显示学生信息,text1显示学生姓名,text2显示学生年龄。首先封装一个Student类。

class Student {
		String name;
		int age;
		
		public Student(String name, int age) {
			this.name = name;
			this.age = age;
		}
}

下一步就是要自定义一个StudentAdapter

class StudentAdapter extends ArrayAdapter<Student> {
		LayoutInflater inflator;
		
		public StudentAdapter(Context context) {
			super(context, 0);
			inflator = LayoutInflater.from(context);
		}
		
		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			if (convertView == null) {
				convertView = inflator.inflate(android.R.layout.simple_list_item_2, parent, false);
			}
			
			TextView text1 = (TextView)convertView.findViewById(android.R.id.text1);
			TextView text2 = (TextView)convertView.findViewById(android.R.id.text2);
			
			Student s = this.getItem(position);
			
			text1.setText(s.name);
			text2.setText("" + s.age);
			
			return convertView;
		}
	}

整个Activity的实现:

public class MainActivity extends Activity {

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		ListView list = (ListView) findViewById(R.id.list);

		StudentAdapter adapter = new StudentAdapter(this);
		adapter.add(new Student("A", 20));
		adapter.add(new Student("B", 21));

		list.setAdapter(adapter);
	}

	class StudentAdapter extends ArrayAdapter<Student> {
		LayoutInflater inflator;

		public StudentAdapter(Context context) {
			super(context, 0);
			inflator = LayoutInflater.from(context);
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			if (convertView == null) {
				convertView = inflator.inflate(
						android.R.layout.simple_list_item_2, parent, false);
			}

			TextView text1 = (TextView) convertView
					.findViewById(android.R.id.text1);
			TextView text2 = (TextView) convertView
					.findViewById(android.R.id.text2);

			Student s = this.getItem(position);

			text1.setText(s.name);
			text2.setText("" + s.age);

			return convertView;
		}
	}

	class Student {
		String name;
		int age;

		public Student(String name, int age) {
			this.name = name;
			this.age = age;
		}
	}
}

device

需要重写的最重要的一个方法是getView(),它控制数据的显示方式。

总结

综上所述,你可以自定义ListView中每一行数据项需要的布局,如果只显示文本,指定一个TextView控件即可。如

ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
				android.R.layout.simple_list_item_2, android.R.id.text1, items);

 

如果要显示的更丰富,除了自定义布局,还要重写getView()控制显示。