ListView就是列表组件,一般通过继承ListActivity使用系统提供的ListView.
所有的AdapterView组件都需要有一个对应的Adapter作为适配器来显示列表中元素的布局方式
见思维导图
ArrayAdapter: 数组或集合的适配器。
例:
private final String[] mous = {
"郭嘉",
"荀攸",
"荀彧",
"程昱",
"戏志才",
"徐庶"
};
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,mous);
也可以在XML文件中用android:entries属性指定绑定的数组资源文件
资源文件存放在value文件夹下
如:
android:entries="@array/book"
<string-array name="book" >
<item >1</item>
<item >2</item>
<item >3</item>
<item >3</item>
</string-array>
例子
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >
<ListView
android:id="@+id/lv"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</LinearLayout>
package com.light.android.study;
import android.app.Activity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;
public class MainActivity extends Activity {
private final String[] mous = {
"郭嘉",
"荀攸",
"荀彧",
"程昱",
"戏志才",
"徐庶"
};
private ListView lv;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
initAdapter();
}
private void init(){
lv = (ListView) findViewById(R.id.lv);
}
private void initAdapter(){
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,mous);
lv.setAdapter(adapter);
}
}
效果:
SimpleAdapter:简单的Adapter实现
SimpleAdapter(Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to)
第一个参数是Context对象
第二个参数是保存有每一行数据的Map构成的List对象,也就是说,每一行数据里的每一个属性都由它的名字和它的值构成一个键值对,多个属性有多个键值对,每一行的多个键值对构成这一行的一个Map对象,这一行的Map对象对应到这个List中.
第三个参数布局文件Id
第四个参数Map对象中的多个键值对的key值
第五个参数布局文件中用来显示内容的组件ID
SimpleAdapter绑定数据到视图分两个阶段
1.首先,如果设置了SimpleAdapter.ViewBinder,那么这个设置的ViewBinder的setViewValue(android.view.View, Object, String)将被调用.如果setViewValue的返回值是true,则表示绑定已经完成,将不再调用系统默认的绑定实现.
2.如果返回值为false,视图将按以下顺序绑定数据:
•如果View实现了Checkable(例如CheckBox),期望绑定值是一个布尔类型.
•TextView.期望绑定值是一个字符串类型,通过调用setViewText(TextView, String)绑定.
•ImageView,期望绑定值是一个资源id或者一个字符串,通过调用setViewImage(ImageView, int) 或 setViewImage(ImageView, String)绑定数据.
如果没有一个合适的绑定发生将会抛出IllegalStateException.
例子:
布局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<!-- 定义一个List -->
<ListView
android:id="@+id/mylist"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical" >
<!-- 定义一个ImageView,用于作为列表项的一部分。 -->
<ImageView
android:id="@+id/header"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
tools:ignore="ContentDescription" />
<!-- 定义一个TextView,用于作为列表项的一部分。 -->
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:paddingLeft="10dp"
android:textSize="16sp" />
</LinearLayout>
package com.light.android.study;
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 {
private String[] names = new String[] { "杜甫", "弄玉", "清照", "李白" };
private int[] imageIds = new int[] { R.drawable.tiger, R.drawable.nongyu,
R.drawable.qingzhao, R.drawable.libai };
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
List<Map<String, Object>> listItems = new ArrayList<Map<String, Object>>();
for (int i = 0; i < names.length; i++) {
Map<String, Object> map = new HashMap<String, Object>();
map.put("header", imageIds[i]);
map.put("personName", names[i]);
listItems.add(map);
}
//創建SimpleAdapter
SimpleAdapter simpleAdapter = new SimpleAdapter(this, listItems,
R.layout.list_item_layout, new String[] { "personName", "header" },
new int[] { R.id.name, R.id.header });
ListView list = (ListView) findViewById(R.id.mylist);
list.setAdapter(simpleAdapter);
}
}
效果:
CursorAdapter:
Cursor型集合的适配器,与数据库连接的桥梁
其中游标携带的结果集中必须有列名为“_id”的列,否则这个类无法工作.
getView()
每一项显示的设置
bindView()
把数据和已经生成的View绑定在一起
newView()
新建一个View
CursorAdapter中源码 getView的实现
public View getView(int position, View convertView, ViewGroup parent) {
View v;
if (convertView == null) {
v = newView(mContext, mCursor, parent);
} else {
v = convertView;
}
bindView(v, mContext, mCursor);
return v;
}
getView首先使用已经存在的View,如果没有就调用newView 产生一个,然后把数据bind上去
我们一般使用其子类SimpleCursorAdapter来实现查询出来的数据List的Adapter
SimpleCursorAdapter(Context context,int layout,Cursor c,String[] from,int[] to,int flags)
context:当前Context对象
layout:布局文件Id
c:集合
from:需要绑定的集合中的列的名字
to:显示项目的View的id集合,在layout布局文件中定义
flags:用来判断适配器的行为标志
建议使用CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER
适配器会在游标上注册一个内容观测器,当通知到达时会调用 onContentChanged() 方法.使用该标志位时要注意:在注册观察器时需要先解除当前游标与适配器的关联,防止发生泄漏.
Android 3.0引入了CursorLoader实现异步加载数据,为了避免同步查询数据库时阻塞UI线程的问题。所以一般先将SimpleCursorAdapter中的Cursor对象放空,然后用CursorLoader对象加载数据,再放入适配器。
例子:
布局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >
<ListView
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</LinearLayout>
Item布局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="64dip"
android:orientation="horizontal"
android:gravity="center_vertical"
android:paddingLeft="8dip">
<TextView android:id="@android:id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="18sp"
android:gravity="center_vertical"
android:singleLine="true"
android:fadingEdge="horizontal"
android:fadingEdgeLength="3dip"
android:ellipsize="marquee"
/>
</LinearLayout>
package com.light.android.study;
import android.app.ListActivity;
import android.app.LoaderManager.LoaderCallbacks;
import android.content.Context;
import android.content.CursorLoader;
import android.content.Loader;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.widget.SimpleCursorAdapter;
//實現接口作為CursorLoader
public class MainActivity extends ListActivity implements LoaderCallbacks<Cursor> {
private SimpleCursorAdapter mAdapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Create an empty adapter we will use to display the loaded data.
mAdapter = new SimpleCursorAdapter(MainActivity.this,
R.layout.contacts_list_item, null,
new String[] { ContactsContract.Contacts.DISPLAY_NAME },
new int[] { android.R.id.text1 },
0);
getListView().setAdapter(mAdapter);
//初始化Loader
//第一個參數 為這個Loader對象指定唯一的标识ID,第二个可选参数,用来支持Loader的构造方法,
//第三个参数是LoaderCallbacks接口类型
getLoaderManager().initLoader(0, null, this);
}
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
// 去数据库读取数据等要消耗大量时间的操作放在
// 自定义 CursorLoader 的 onLoadInBackground
return new MyCursorLoader(getApplicationContext());
}
public void onLoadFinished(Loader<Cursor> arg0, Cursor cursor) {
// Swap the new cursor in. (The framework will take care of closing the
// old cursor once we return.)
mAdapter.swapCursor(cursor);
}
public void onLoaderReset(Loader<Cursor> arg0) {
// This is called when the last Cursor provided to onLoadFinished()
// above is about to be closed. We need to make sure we are no
// longer using it.
mAdapter.swapCursor(null);
}
public static class MyCursorLoader extends CursorLoader {
String[] mContactProjection = { ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME };
private Context mContext;
public MyCursorLoader(Context context) {
super(context);
mContext = context;
}
/**
* 4.自定义 CursorLoader 的 onLoadInBackground
* 会返回一个Cursor,这里给SimpleCursorAdapter用
* 来填充数据。查询数据等操作放在这里执行
*/
@Override
protected Cursor onLoadInBackground() {
Cursor cursor = mContext.getContentResolver().query(
ContactsContract.Contacts.CONTENT_URI, mContactProjection,
null, null, null);
return cursor;
}
}
}
效果:
最后看下自定义BaseAdapter
需要实现下列方法:
abstract Object getItem(int position)
得到位于position位置的项
abstract int getCount()
得到项目总数
abstract long getItemId(int position)
得到位于position位置的项的Id
abstract int getItemViewType(int position)
得到位于position位置的项的类型
abstract View getView(int position,View convertVeiw,ViewGroup parent)
每一项显示的设置
在getView方法中需要缓存加载View优化ListView
官方建议使用ViewHolder,其实就是单例
例:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
final LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.list_item_icon_text, null);
holder = new ViewHolder();
holder.icon = (ImageView) convertView.findViewById(R.id.icon);
holder.text = (TextView) convertView.findViewById(R.id.text);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.icon.setImageResource(R.drawable.icon);
holder.text.setText(mData[position]);
return convertView;
}
static class ViewHolder {
ImageView icon;
TextView text;
}

浙公网安备 33010602011771号