您的位置:首页 > 移动开发 > Android开发

Android ListView入门知识--各种Adapter配合使用

2012-03-24 11:48 531 查看
在android开发中ListView是比较常用的组件,它以列表的形式展示具体内容,并且能够根据数据的长度自适应显示。
列表的显示需要三个元素:
1.ListVeiw 用来展示列表的View。
2.适配器 用来把数据映射到ListView上的中介。
3.数据 具体的将被映射的字符串,图片,或者基本组件。
根据列表的适配器类型,列表分为三种,ArrayAdapter,SimpleAdapter和SimpleCursorAdapter
其中以ArrayAdapter最为简单,只能展示一行字。SimpleAdapter有最好的扩充性,可以自定义出各种效果。SimpleCursorAdapter可以认为是SimpleAdapter对数据库的简单结合,可以方便的把数据库的内容以列表的形式展示出来。
=====================================================================
我们从最简单的ListView开始---ArrayAdapter

[java]
view plaincopyprint?

01 /**
02 * @author allin
03 *
04 */
05 public class MyListView extends Activity {
06
07 private ListView listView;
08 //private List<String> data = new ArrayList<String>();

09 @Override
10 public void onCreate(Bundle savedInstanceState){
11 super.onCreate(savedInstanceState);
12
13 listView = new ListView(this);
14 listView.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_expandable_list_item_1,getData()));
15 setContentView(listView);
16 }
17
18
19
20 private List<String> getData(){
21
22 List<String> data = new ArrayList<String>();
23 data.add("测试数据1");
24 data.add("测试数据2");
25 data.add("测试数据3");
26 data.add("测试数据4");
27
28 return data;
29 }
30 }

[java]
view plaincopyprint?

/**
02     * @author allin
03     *
04     */
05    public class MyListView2 extends Activity {
06
07        private ListView listView;
08        //private List<String> data = new ArrayList<String>();

09        @Override
10        public void onCreate(Bundle savedInstanceState){
11            super.onCreate(savedInstanceState);
12
13            listView = new ListView(this);
14
15            Cursor cursor = getContentResolver().query(People.CONTENT_URI, null, null, null, null);
16            startManagingCursor(cursor);
17
18            ListAdapter listAdapter = new SimpleCursorAdapter(this, android.R.layout.simple_expandable_list_item_1,
19                    cursor,
20                    new String[]{People.NAME},
21                    new int[]{android.R.id.text1});
22
23            listView.setAdapter(listAdapter);
24            setContentView(listView);
25        }
26
27
28    }

/**
02     * @author allin
03     *
04     */
05    public class MyListView2 extends Activity {
06
07        private ListView listView;
08        //private List<String> data = new ArrayList<String>();
09        @Override
10        public void onCreate(Bundle savedInstanceState){
11            super.onCreate(savedInstanceState);
12
13            listView = new ListView(this);
14
15            Cursor cursor = getContentResolver().query(People.CONTENT_URI, null, null, null, null);
16            startManagingCursor(cursor);
17
18            ListAdapter listAdapter = new SimpleCursorAdapter(this, android.R.layout.simple_expandable_list_item_1,
19                    cursor,
20                    new String[]{People.NAME},
21                    new int[]{android.R.id.text1});
22
23            listView.setAdapter(listAdapter);
24            setContentView(listView);
25        }
26
27
28    }


Cursor cursor = getContentResolver().query(People.CONTENT_URI, null, null, null, null);先获得一个指向系统通讯录数据库的Cursor对象获得数据来源。
startManagingCursor(cursor);我们将获得的Cursor对象交由Activity管理,这样Cursor的生命周期和Activity便能够自动同步,省去自己手动管理Cursor。
注意:需要在AndroidManifest.xml中如权限:<uses-permission android:name="android.permission.READ_CONTACTS"></uses-permission>

SimpleCursorAdapter 构造函数前面3个参数和ArrayAdapter是一样的,最后两个参数:一个包含数据库的列的String型数组,一个包含布局文件中对应组件id的int型数组。其作用是自动的将String型数组所表示的每一列数据映射到布局文件对应id的组件上。上面的代码,将NAME列的数据一次映射到布局文件的id为text1的组件上。
运行后效果如下图:



===================================================================
SimpleAdapter
simpleAdapter的扩展性最好,可以定义各种各样的布局出来,可以放上ImageView(图片),还可以放上Button(按钮),CheckBox(复选框)等等。下面的代码都直接继承了ListActivity,ListActivity和普通的Activity没有太大的差别,不同就是对显示ListView做了许多优化,方面显示而已。
下面的程序是实现一个带有图片的类表。
首先需要定义好一个用来显示每一个列内容的xml
vlist.xml

[html]
view plaincopyprint?

<?xml version="1.0" encoding="utf-8"?>
02 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
03 android:orientation="horizontal" android:layout_width="fill_parent"
04 android:layout_height="fill_parent">
05
06
07 <ImageView android:id="@+id/img"
08 android:layout_width="wrap_content"
09 android:layout_height="wrap_content"
10 android:layout_margin="5px"/>
11
12 <LinearLayout android:orientation="vertical"
13 android:layout_width="wrap_content"
14 android:layout_height="wrap_content">
15
16 <TextView android:id="@+id/title"
17 android:layout_width="wrap_content"
18 android:layout_height="wrap_content"
19 android:textColor="#FFFFFFFF"
20 android:textSize="22px" />
21 <TextView android:id="@+id/info"
22 android:layout_width="wrap_content"
23 android:layout_height="wrap_content"
24 android:textColor="#FFFFFFFF"
25 android:textSize="13px" />
26
27 </LinearLayout>
28
29
30 </LinearLayout>

[java]
view plaincopyprint?

/**
02     * @author allin
03     *
04     */
05    public class MyListView3 extends ListActivity {
06
07
08        // private List<String> data = new ArrayList<String>();

09        @Override
10        public void onCreate(Bundle savedInstanceState) {
11            super.onCreate(savedInstanceState);
12
13            SimpleAdapter adapter = new SimpleAdapter(this,getData(),R.layout.vlist,
14                    new String[]{"title","info","img"},
15                    new int[]{R.id.title,R.id.info,R.id.img});
16            setListAdapter(adapter);
17        }
18
19        private List<Map<String, Object>> getData() {
20            List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
21
22            Map<String, Object> map = new HashMap<String, Object>();
23            map.put("title", "G1");
24            map.put("info", "google 1");
25            map.put("img", R.drawable.i1);
26            list.add(map);
27
28            map = new HashMap<String, Object>();
29            map.put("title", "G2");
30            map.put("info", "google 2");
31            map.put("img", R.drawable.i2);
32            list.add(map);
33
34            map = new HashMap<String, Object>();
35            map.put("title", "G3");
36            map.put("info", "google 3");
37            map.put("img", R.drawable.i3);
38            list.add(map);
39
40            return list;
41        }
42    }

/**
02     * @author allin
03     *
04     */
05    public class MyListView3 extends ListActivity {
06
07
08        // private List<String> data = new ArrayList<String>();
09        @Override
10        public void onCreate(Bundle savedInstanceState) {
11            super.onCreate(savedInstanceState);
12
13            SimpleAdapter adapter = new SimpleAdapter(this,getData(),R.layout.vlist,
14                    new String[]{"title","info","img"},
15                    new int[]{R.id.title,R.id.info,R.id.img});
16            setListAdapter(adapter);
17        }
18
19        private List<Map<String, Object>> getData() {
20            List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
21
22            Map<String, Object> map = new HashMap<String, Object>();
23            map.put("title", "G1");
24            map.put("info", "google 1");
25            map.put("img", R.drawable.i1);
26            list.add(map);
27
28            map = new HashMap<String, Object>();
29            map.put("title", "G2");
30            map.put("info", "google 2");
31            map.put("img", R.drawable.i2);
32            list.add(map);
33
34            map = new HashMap<String, Object>();
35            map.put("title", "G3");
36            map.put("info", "google 3");
37            map.put("img", R.drawable.i3);
38            list.add(map);
39
40            return list;
41        }
42    }


使用simpleAdapter的数据用一般都是HashMap构成的List,list的每一节对应ListView的每一行。HashMap的每个键值数据映射到布局文件中对应id的组件上。因为系统没有对应的布局文件可用,我们可以自己定义一个布局vlist.xml。下面做适配,new一个SimpleAdapter参数一次是:this,布局文件(vlist.xml),HashMap的
title 和 info,img。布局文件的组件id,title,info,img。布局文件的各组件分别映射到HashMap的各元素上,完成适配。

运行效果如下图:



========================================================================
有按钮的ListView---重写继承BaseAdapter
但是有时候,列表不光会用来做显示用,我们同样可以在在上面添加按钮。添加按钮首先要写一个有按钮的xml文件,然后自然会想到用上面的方法定义一个适配器,然后将数据映射到布局文件上。但是事实并非这样,因为按钮是无法映射的,即使你成功的用布局文件显示出了按钮也无法添加按钮的响应,这时就要研究一下ListView是如何现实的了,而且必须要重写一个类继承BaseAdapter。下面的示例将显示一个按钮和一个图片,两行字如果单击按钮将删除此按钮的所在行。并告诉你ListView究竟是如何工作的。
效果如下:



vlist2.xml

[html]
view plaincopyprint?

<?xml version="1.0" encoding="utf-8"?>
02 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
03 android:orientation="horizontal"
04 android:layout_width="fill_parent"
05 android:layout_height="fill_parent">
06
07
08 <ImageView android:id="@+id/img"
09 android:layout_width="wrap_content"
10 android:layout_height="wrap_content"
11 android:layout_margin="5px"/>
12
13 <LinearLayout android:orientation="vertical"
14 android:layout_width="wrap_content"
15 android:layout_height="wrap_content">
16
17 <TextView android:id="@+id/title"
18 android:layout_width="wrap_content"
19 android:layout_height="wrap_content"
20 android:textColor="#FFFFFFFF"
21 android:textSize="22px" />
22 <TextView android:id="@+id/info"
23 android:layout_width="wrap_content"
24 android:layout_height="wrap_content"
25 android:textColor="#FFFFFFFF"
26 android:textSize="13px" />
27
28 </LinearLayout>
29
30
31 <Button android:id="@+id/view_btn"
32 android:layout_width="wrap_content"
33 android:layout_height="wrap_content"
34 android:text="@string/s_view_btn"
35 android:layout_gravity="bottom|right" />
36 </LinearLayout>

[java]
view plaincopyprint?

/**
002     * @author allin
003     *
004     */
005    public class MyListView4 extends ListActivity {
006
007
008        private List<Map<String, Object>> mData;
009
010        @Override
011        public void onCreate(Bundle savedInstanceState) {
012            super.onCreate(savedInstanceState);
013            mData = getData();
014            MyAdapter adapter = new MyAdapter(this);
015            setListAdapter(adapter);
016        }
017
018        private List<Map<String, Object>> getData() {
019            List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
020
021            Map<String, Object> map = new HashMap<String, Object>();
022            map.put("title", "G1");
023            map.put("info", "google 1");
024            map.put("img", R.drawable.i1);
025            list.add(map);
026
027            map = new HashMap<String, Object>();
028            map.put("title", "G2");
029            map.put("info", "google 2");
030            map.put("img", R.drawable.i2);
031            list.add(map);
032
033            map = new HashMap<String, Object>();
034            map.put("title", "G3");
035            map.put("info", "google 3");
036            map.put("img", R.drawable.i3);
037            list.add(map);
038
039            return list;
040        }
041
042        // ListView 中某项被选中后的逻辑

043        @Override
044        protected void onListItemClick(ListView l, View v, int position, long id) {
045
046            Log.v("MyListView4-click", (String)mData.get(position).get("title"));
047        }
048
049        /**
050         * listview中点击按键弹出对话框
051         */
052        public void showInfo(){
053            new AlertDialog.Builder(this)
054            .setTitle("我的listview")
055            .setMessage("介绍...")
056            .setPositiveButton("确定", new DialogInterface.OnClickListener() {
057                @Override
058                public void onClick(DialogInterface dialog, int which) {
059                }
060            })
061            .show();
062
063        }
064
065
066
067        public final class ViewHolder{
068            public ImageView img;
069            public TextView title;
070            public TextView info;
071            public Button viewBtn;
072        }
073
074
075        public class MyAdapter extends BaseAdapter{
076
077            private LayoutInflater mInflater;
078
079
080            public MyAdapter(Context context){
081                this.mInflater = LayoutInflater.from(context);
082            }
083            @Override
084            public int getCount() {
085                // TODO Auto-generated method stub

086                return mData.size();
087            }
088
089            @Override
090            public Object getItem(int arg0) {
091                // TODO Auto-generated method stub

092                return null;
093            }
094
095            @Override
096            public long getItemId(int arg0) {
097                // TODO Auto-generated method stub

098                return 0;
099            }
100
101            @Override
102            public View getView(int position, View convertView, ViewGroup parent) {
103
104                ViewHolder holder = null;
105                if (convertView == null) {
106
107                    holder=new ViewHolder();
108
109                    convertView = mInflater.inflate(R.layout.vlist2, null);
110                    holder.img = (ImageView)convertView.findViewById(R.id.img);
111                    holder.title = (TextView)convertView.findViewById(R.id.title);
112                    holder.info = (TextView)convertView.findViewById(R.id.info);
113                    holder.viewBtn = (Button)convertView.findViewById(R.id.view_btn);
114                    convertView.setTag(holder);
115
116                }else {
117
118                    holder = (ViewHolder)convertView.getTag();
119                }
120
121
122                holder.img.setBackgroundResource((Integer)mData.get(position).get("img"));
123                holder.title.setText((String)mData.get(position).get("title"));
124                holder.info.setText((String)mData.get(position).get("info"));
125
126                holder.viewBtn.setOnClickListener(new View.OnClickListener() {
127
128                    @Override
129                    public void onClick(View v) {
130                        showInfo();
131                    }
132                });
133
134
135                return convertView;
136            }
137
138        }
139
140
141
142
143    }

/**
002     * @author allin
003     *
004     */
005    public class MyListView4 extends ListActivity {
006
007
008        private List<Map<String, Object>> mData;
009
010        @Override
011        public void onCreate(Bundle savedInstanceState) {
012            super.onCreate(savedInstanceState);
013            mData = getData();
014            MyAdapter adapter = new MyAdapter(this);
015            setListAdapter(adapter);
016        }
017
018        private List<Map<String, Object>> getData() {
019            List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
020
021            Map<String, Object> map = new HashMap<String, Object>();
022            map.put("title", "G1");
023            map.put("info", "google 1");
024            map.put("img", R.drawable.i1);
025            list.add(map);
026
027            map = new HashMap<String, Object>();
028            map.put("title", "G2");
029            map.put("info", "google 2");
030            map.put("img", R.drawable.i2);
031            list.add(map);
032
033            map = new HashMap<String, Object>();
034            map.put("title", "G3");
035            map.put("info", "google 3");
036            map.put("img", R.drawable.i3);
037            list.add(map);
038
039            return list;
040        }
041
042        // ListView 中某项被选中后的逻辑
043        @Override
044        protected void onListItemClick(ListView l, View v, int position, long id) {
045
046            Log.v("MyListView4-click", (String)mData.get(position).get("title"));
047        }
048
049        /**
050         * listview中点击按键弹出对话框
051         */
052        public void showInfo(){
053            new AlertDialog.Builder(this)
054            .setTitle("我的listview")
055            .setMessage("介绍...")
056            .setPositiveButton("确定", new DialogInterface.OnClickListener() {
057                @Override
058                public void onClick(DialogInterface dialog, int which) {
059                }
060            })
061            .show();
062
063        }
064
065
066
067        public final class ViewHolder{
068            public ImageView img;
069            public TextView title;
070            public TextView info;
071            public Button viewBtn;
072        }
073
074
075        public class MyAdapter extends BaseAdapter{
076
077            private LayoutInflater mInflater;
078
079
080            public MyAdapter(Context context){
081                this.mInflater = LayoutInflater.from(context);
082            }
083            @Override
084            public int getCount() {
085                // TODO Auto-generated method stub
086                return mData.size();
087            }
088
089            @Override
090            public Object getItem(int arg0) {
091                // TODO Auto-generated method stub
092                return null;
093            }
094
095            @Override
096            public long getItemId(int arg0) {
097                // TODO Auto-generated method stub
098                return 0;
099            }
100
101            @Override
102            public View getView(int position, View convertView, ViewGroup parent) {
103
104                ViewHolder holder = null;
105                if (convertView == null) {
106
107                    holder=new ViewHolder();
108
109                    convertView = mInflater.inflate(R.layout.vlist2, null);
110                    holder.img = (ImageView)convertView.findViewById(R.id.img);
111                    holder.title = (TextView)convertView.findViewById(R.id.title);
112                    holder.info = (TextView)convertView.findViewById(R.id.info);
113                    holder.viewBtn = (Button)convertView.findViewById(R.id.view_btn);
114                    convertView.setTag(holder);
115
116                }else {
117
118                    holder = (ViewHolder)convertView.getTag();
119                }
120
121
122                holder.img.setBackgroundResource((Integer)mData.get(position).get("img"));
123                holder.title.setText((String)mData.get(position).get("title"));
124                holder.info.setText((String)mData.get(position).get("info"));
125
126                holder.viewBtn.setOnClickListener(new View.OnClickListener() {
127
128                    @Override
129                    public void onClick(View v) {
130                        showInfo();
131                    }
132                });
133
134
135                return convertView;
136            }
137
138        }
139
140
141
142
143    }


下面将对上述代码,做详细的解释,listView在开始绘制的时候,系统首先调用getCount()函数,根据他的返回值得到listView的长度(这也是为什么在开始的第一张图特别的标出列表长度),然后根据这个长度,调用getView()逐一绘制每一行。如果你的getCount()返回值是0的话,列表将不显示同样return
1,就只显示一行。
系统显示列表时,首先实例化一个适配器(这里将实例化自定义的适配器)。当手动完成适配时,必须手动映射数据,这需要重写getView()方法。系统在绘制列表的每一行的时候将调用此方法。getView()有三个参数,position表示将显示的是第几行,covertView是从布局文件中inflate来的布局。我们用LayoutInflater的方法将定义好的vlist2.xml文件提取成View实例用来显示。然后将xml文件中的各个组件实例化(简单的findViewById()方法)。这样便可以将数据对应到各个组件上了。但是按钮为了响应点击事件,需要为它添加点击监听器,这样就能捕获点击事件。至此一个自定义的listView就完成了,现在让我们回过头从新审视这个过程。系统要绘制ListView了,他首先获得要绘制的这个列表的长度,然后开始绘制第一行,怎么绘制呢?调用getView()函数。在这个函数里面首先获得一个View(实际上是一个ViewGroup),然后再实例并设置各个组件,显示之。好了,绘制完这一行了。那再绘制下一行,直到绘完为止。在实际的运行过程中会发现listView的每一行没有焦点了,这是因为Button抢夺了listView的焦点,只要布局文件中将Button设置为没有焦点就OK了。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: