在Android中使用一个控件,一般要有两样东西,一是样式,二是数据。
在第一篇中,我们的ListView使用了Android提供的默认样式android.R.layout.simple_list_item_1,这个样式其实就是每个item是一个TextView。数据我们是声明了一个List并赋值的。最后,我们用了这样一句代码实现了把这些绑定到ListView中:
ArrayAdapter<String> adpater = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,data);
概述
所以这篇主要的学习内容是在ListView中使用的Adpter。
说起Adapter,我第一个想到的就是适配器模式,虽然设计模式学得不怎么样,但是这个词还是记着的。让我们看一下在API中对Adapter的说明:
An Adapter object acts as a bridge between an AdapterView
and
the underlying data for that view. The Adapter provides access to the data items. The Adapter is also responsible for making a View
for
each item in the data set.(Adapter对象在AdapterView和数据之间扮演者桥梁的角色,Adapter提供了通向数据项的途径。Adapter还负责为数据集中的每一个数据项生成view)
Adapter的子类:
以上两图来自(http://www.cnblogs.com/devinzhang/archive/2012/01/20/2328334.html)
Adapter有很多子类,ListActivity中用到的是ListAdpter,ListActivity提供setListAdapter方法来出入使用的Adpter
public void setListAdapter(ListAdapter adapter) { synchronized (this) { ensureList(); mAdapter = adapter; mList.setAdapter(adapter); } }
ListAdpter在API中的描述如下:
Extended Adapter
that
is the bridge between a ListView
and
the data that backs the list. Frequently that data comes from a Cursor, but that is not required. The ListView can display any data provided that it is wrapped in a ListAdapter.(ListAdapter继承了Adapter,作为ListView和数据集之间的桥梁。通常,数据来源于Cursor,但是不是必须的。ListView可以显示任何被ListAdapter所包装的数据)
但是ListAdpter是个接口,我们用的时候不会直接用它,而是用到实现这个接口的ArrayAdapter<T>,SimpleAdapter,SimpleCursorAdapter。
接下来,我是介绍这几种adapter的用法:
ArrayAdapter
ArrayAdapter是安卓提供的一个支持泛型的adapter,这个有点是比较方便,而且有默认定义好的几种样式供选择。
ArrayAdapter提供了几种构造方法:
Public Constructors | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
|
Constructor
|
||||||||||
|
Constructor
|
||||||||||
|
Constructor
|
||||||||||
|
Constructor
|
||||||||||
|
Constructor
|
||||||||||
|
Constructor
|
Parameters
context | The current context. |
---|---|
resource | The resource ID for a layout file containing a layout to use when instantiating views.(Item对应的布局文件的id) |
textViewResourceId | The id of the TextView within the layout resource to be populated(TextView对应的布局文件的id) |
objects | The objects to represent in the ListView.(要显示的数据集) |
安卓为我们提供了几种查用的Item的布局文件:比如我在第一篇的例子中用到的android.R.layout.simple_list_item_1,这个布局文件中只有一个TextView
我们可以看一下它的源码:
<?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/text1" android:layout_width="match_parent" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceListItemSmall" android:gravity="center_vertical" android:paddingStart="?android:attr/listPreferredItemPaddingStart" android:paddingEnd="?android:attr/listPreferredItemPaddingEnd" android:minHeight="?android:attr/listPreferredItemHeightSmall" />我们也可以使用其它Android提供的配置文件
需要注意的是,因为我在第一篇的例子中使用的android.R.layout.simple_list_item_1这个样式,在这个样式中只有一个TextView,所以我可以用只有三个参数的构造函数
ArrayAdapter<String> adpter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,data);
如果在配置文件中有不止一个view,则需要指定数据放到哪个view中,例如如果使用simple_list_item_single_choice在这个配置文件中有两个TextView则需要四个参数的构造函数
ArrayAdapter<String> adpter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_single_choice,android.R.id.text1,data);
这两个的运行结果如下图
SimpleAdapter
相对于ArrayAdapter,SimpleAdapter提供了更加灵活的构建ListView的方式。
我们看一下它的构造函数:
Public Constructors | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
|
Constructor
|
Parameters
context | The context where the View associated with this SimpleAdapter is running |
---|---|
data |
A List of Maps. Each entry in the List corresponds to one row in the list. The Maps contain the data for each row, and should include all the entries specified in "from" |
resource | Resource identifier of a view layout that defines the views for this list item. The layout file should include at least those named views defined in "to" |
from | A list of column names that will be added to the Map associated with each item. |
to | The views that should display column in the "from" parameter. These should all be TextViews. The first N views in this list are given the values of the first N columns in the from parameter. |
<?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="match_parent" android:orientation="horizontal" > <ImageView android:id="@+id/image" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="20dp" /> <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="20dp" android:layout_gravity="center_vertical" /> </LinearLayout>
Activity:
package com.example.listview4; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import android.os.Bundle; import android.widget.SimpleAdapter; import android.app.ListActivity; public class MainActivity extends ListActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); SimpleAdapter adapter = new SimpleAdapter(this, getData(), R.layout.item, new String[] {"image","text"}, new int[] {R.id.image,R.id.text}); setListAdapter(adapter); } private List<Map<String,Object>> getData(){ List<Map<String,Object>> list = new ArrayList<Map<String,Object>>(); Map<String,Object> map = new HashMap<String,Object>(); map.put("image", R.drawable.ic_launcher); map.put("text", "测试1"); list.add(map); Map<String,Object> map1 = new HashMap<String,Object>(); map1.put("image", R.drawable.ic_launcher); map1.put("text", "测试2"); list.add(map1); Map<String,Object> map2 = new HashMap<String,Object>(); map2.put("image", R.drawable.ic_launcher); map2.put("text", "测试3"); list.add(map2); return list; } }
下面是运行结果:
SimpleCursorAdapter
Public Constructors | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
|
This constructor was deprecated in API level 11. This option is discouraged, as it results in Cursor queries being performed on the application‘s UI
thread and thus can cause poor responsiveness or even Application Not Responding errors. As an alternative, use
LoaderManager with
a CursorLoader . |
||||||||||
|
Standard constructor.
|
Parameters
context | The context where the ListView associated with this SimpleListItemFactory is running |
---|---|
layout | resource identifier of a layout file that defines the views for this list item. The layout file should include at least those named views defined in "to" |
c | The database cursor. Can be null if the cursor is not available yet. |
from | A list of column names representing the data to bind to the UI. Can be null if the cursor is not available yet. |
to |
The views that should display column in the "from" parameter. These should all be TextViews. The first N views in this list are given the values
of the first N columns in the from parameter. Can be null if the cursor is not available yet. |
flags |
Flags used to determine the behavior of the adapter, as per CursorAdapter(Context,
Cursor, int) . |
参数和前面的大同小异,就不介绍了
下面这段代码是参考API中提供的例子写的,但是代码中获取联系人信息的方式在目前的API中已经不被推荐使用,所以仅供学习参考
package com.example.listview5; import android.app.ListActivity; import android.database.Cursor; import android.os.Bundle; import android.provider.Contacts.People; import android.widget.ListAdapter; import android.widget.SimpleCursorAdapter; @SuppressWarnings("deprecation") public class MainActivity extends ListActivity { @Override protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); // 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. Cursor mCursor = this.getContentResolver().query(People.CONTENT_URI, null, null, null, People.TIMES_CONTACTED); 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, mCursor, new String[] {People.NAME, People.TIMES_CONTACTED}, new int[] {android.R.id.text1, android.R.id.text2}); // Bind to our new adapter. setListAdapter(adapter); } }