public class
ListActivity
extends Activity
java.lang.Object
android.content.Context
android.content.ContextWrapper
android.view.ContextThemeWrapper
android.app.Activity
android.app.ListActivity
Class Overview
ListActivity显示一个绑定到数组或游标这些数据源的一个列表,并且列表的每一项提供一个点击事件的管理方法,当用户点击其中的列表项的时候就能进行相应的处理。
ListActivity容纳了一个ListView对象,这个对象能够绑定不同的数据源,一般是一个数组或者存储了一组查询结果的游标(Cursor)。
[b]屏幕布局[/b]
ListActivity的默认布局由一个位于屏幕中心的全屏列表构成。但是,如果你不想使用默认的布局,可以在onCreate()方法中通过setContentView()方法设定你自己定制的布局。
如果指定你自己定制的布局,你的布局中必须包含一个id为"@android:id/list"的ListView 。此外,你自定义的view为空时,能够包含另外一个任何类型的view对象。
没有数据(empty list)时,会显示一个TextView中的数据,而ListView视图就会被隐藏,但这个TextView的id必须="android:empty"。
下面的代码示例一个丑陋的自定义屏幕布局。这个布局有一个list,这个list有绿色的背景色,还有一个用来代替的红色的“no data”消息。
<?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"
android:paddingLeft="8dp"
android:paddingRight="8dp">
<ListView android:id="@id/android:list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#00FF00"
android:layout_weight="1"
android:drawSelectorOnTop="false"/>
<TextView id="@id/android:empty"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FF0000"
android:text="No data"/>
</LinearLayout>
[b]总结:[/b]使用ListActivity的目的就是让其帮我管理ListView等等,所以即使是用我们自己的layout时,其名称也要用@id/android:list,@id/android:empty来命名,这样就可以交给ListActivity来管理。
[b]行布局(Row Layout) [/b]
你能够指定列表中一个单独的行的布局。只要在ListAdapter对象中指定一个布局资源就可以了。ListAdapter绑定数据到ListView。
一个ListAdapter构造函数有一个参数来指定每一行的布局资源。此外,它还有另外两个参数来指定哪一个数据域与行布局资源中的对象相关联。这两个参数一般是平行数组。
Android 提供了一些标准的布局资源。这些都在R.layout类中,名字诸如simple_list_item_1, simple_list_item_2, 和two_line_list_item. 下面的布局XML是two_line_list_item, 对于每一行,它分两行来表示数据,一个在上一个在下。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView android:id="@+id/text1"
android:textSize="16sp"
android:textStyle="bold"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView android:id="@+id/text2"
android:textSize="16sp"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
你必须确定绑定到这个布局的每一个TextView对象的数据。下一节就做这一方面的介绍。
[b]绑定数据[/b]
绑定ListActivity的ListView对象和数据,要使用一个实现了ListAdapter接口的类。Android提供了两个标准的list adapters:绑定静态数据(Maps)的SimpleAdapter,和绑定Cursor的SimpleCursorAdapter。
下面这个例子实例一个自定义的ListActivity,它查询Contacts provider的所有contacts,然后绑定Name和Company两个域到ListActivity的ListView中的分为两行的一个列表项。
public class MyListAdapter extends ListActivity {
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// We'll define a custom screen layout here (the one shown above), but
// typically, you could just use the standard ListActivity layout.
setContentView(R.layout.custom_list_activity_view);
// Query for all people contacts using the Contacts.People convenience class.
// Put a managed wrapper around the retrieved cursor so we don't have to worry about
// requerying or closing it as the activity changes state.
mCursor = this.getContentResolver().query(People.CONTENT_URI, null, null, null, null);
startManagingCursor(mCursor);
// Now create a new list adapter bound to the cursor.
// SimpleListAdapter is designed for binding to a Cursor.
ListAdapter adapter = new SimpleCursorAdapter(
this, // Context.
android.R.layout.two_line_list_item,
// Specify the row template to use (here, two columns bound to the two retrieved cursor rows).
mCursor,
// Pass in the cursor to bind to.
new String[] {People.NAME, People.COMPANY},
// Array of cursor columns to bind to.
new int[] {android.R.id.text1, android.R.id.text2});
// Parallel array of which template objects to bind to those columns.
// Bind to our new adapter.
setListAdapter(adapter);
}
}
[b]还有一种绑定数据的方法[/b]
CursorAdapter有两个子类SimpleCursorAdapter,ResourceCursorAdapter(抽象类)。在CursorAdapter中有两个方法:newView()和bindView()方法,newView方法用来new一个RowLayout,bindView方法用来向这个新的RowLayout绑定数据。有人会说,这不是太麻烦了吗,有这个必要吗?当然有必要啊,因为有些数据不能用SimpleCursorAdapter来进行绑定的。
private final class ContactListItemAdapter extends ResourceCursorAdapter {
public ContactListItemAdapter(Context context, int layout, Cursor c) {
super(context, layout, c);
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
final ContactListItemCache cache = (ContactListItemCache) view.getTag();
TextView nameView = cache.nameView;
QuickContactBadge photoView = cache.photoView;
cursor.copyStringToBuffer(SUMMARY_NAME_COLUMN_INDEX, cache.nameBuffer);
int size = cache.nameBuffer.sizeCopied;
nameView.setText(cache.nameBuffer.data, 0, size);
final long contactId = cursor.getLong(SUMMARY_ID_COLUMN_INDEX);
final String lookupKey = cursor.getString(SUMMARY_LOOKUP_KEY);
photoView.assignContactUri(Contacts.getLookupUri(contactId, lookupKey));
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
View view = super.newView(context, cursor, parent);
ContactListItemCache cache = new ContactListItemCache();
cache.nameView = (TextView) view.findViewById(R.id.name);
cache.photoView = (QuickContactBadge) view.findViewById(R.id.badge);
view.setTag(cache);
return view;
}
}
[b]注意点[/b]
其中的view.setTag()方法的主要作用是将数据保存到view对象中,这样从另外一个方法或另一个线程中,就可以得到其中的数据,这比用全局变量要好很多,可以访止多线程的情况下,数据的并发访问。