ListView的自定义适配器

网上关于这方面的好的文章:

http://yilee.info/android-diy-listview.html

http://blog.csdn.net/xiaominghimi/article/details/6314704

http://blog.csdn.net/chenzheng_java/article/details/6202586#(本文转自此处作者)

最终结果图:

0_1298610678sd23.gif



代码结构示意图


0_1298610638GseH.gif


vlist2.xml代码:

[xhtml] view plain copy
  1. <?xmlversion="1.0"encoding="utf-8"?>

  2. <LinearLayout

  3. xmlns:android="http://schemas.android.com/apk/res/android"

  4. android:layout_width="fill_parent"

  5. android:layout_height="fill_parent">

  6. <ImageView

  7. android:id="@+id/p_w_picpath"

  8. android:layout_width="wrap_content"

  9. android:layout_height="wrap_content"

  10. android:layout_margin="5px"

  11. />

  12. <LinearLayout

  13. android:layout_width="wrap_content"

  14. android:layout_height="wrap_content"

  15. android:orientation="vertical"

  16. >

  17. <TextView

  18. android:id="@+id/title"

  19. android:layout_width="wrap_content"

  20. android:layout_height="wrap_content"

  21. android:textColor="#FFFFFFFF"

  22. android:textSize="22px"

  23. />

  24. <TextView

  25. android:id="@+id/info"

  26. android:layout_width="wrap_content"

  27. android:layout_height="wrap_content"

  28. android:textColor="#FFFFFFFF"

  29. android:textSize="13px"

  30. />

  31. </LinearLayout>

  32. <Button

  33. android:id="@+id/view_btn"

  34. android:layout_width="wrap_content"

  35. android:layout_height="wrap_content"

  36. android:text="click me"

  37. android:gravity="center"

  38. />

  39. </LinearLayout>


listView3.java代码


[java] view plain copy
  1. package cn.com.android2.listview;  

  2. import java.util.ArrayList;  

  3. import java.util.HashMap;  

  4. import android.app.ListActivity;  

  5. import android.os.Bundle;  

  6. import android.util.Log;  

  7. import android.view.View;  

  8. import android.widget.ListView;  

  9. publicclass listView3 extends ListActivity {  

  10. @Override

  11. publicvoid onCreate(Bundle savedInstanceState) {  

  12. super.onCreate(savedInstanceState);  

  13. // 获取虚拟的数据,数据的格式有严格的要求哦

  14.        ArrayList<HashMap<String, Object>> data = getData();  

  15. //模仿SimpleAdapter实现的自己的adapter

  16.        MyAdapter adapter = new MyAdapter(this, data);  

  17. /**

  18.         * 有些人很迷糊,我们都知道vlist2.xml相当于存储一行数据的组件布局,我们在前边的代码中,都是有一个主布局文件main.xml的,

  19.         * 组件布局文件是放在主布局文件上显示的,一般代码中都是通过setContentView()来指定主布局文件的。为何这里根本就没有用到

  20.         * ,但是listView还能有一个界面来呈现呢。

  21.         * 让我们看看setListAdapter在ListActivity中的实现,

  22.         * public void setListAdapter(ListAdapter adapter) {

  23.            synchronized (this) {

  24.            ensureList();

  25.            mAdapter = adapter;

  26.            mList.setAdapter(adapter);

  27.        }

  28.    }

  29.    里面调用了一个ensureList方法,我们再来看看这个方法:

  30.     private void ensureList() {

  31.        if (mList != null) {

  32.            return;

  33.        }

  34.        setContentView(com.android.internal.R.layout.list_content);

  35.    }

  36.    现在看到了,这里有个 setContentView方法,里面设置了我们的组件在一个android自己提供的界面上显示。

  37.    原来,我们的理论还是适用的,只不过ListActivity给我进行了隐藏实现。

  38.         */

  39.        setListAdapter(adapter);  

  40.    }  

  41. /**

  42.     * @author chenzheng_java

  43.     * @description 准备一些测试数据

  44.     * @return 一个包含了数据信息的hashMap集合

  45.     */

  46. private ArrayList<HashMap<String, Object>> getData(){  

  47.        ArrayList<HashMap<String, Object>> arrayList = new ArrayList<HashMap<String,Object>>();  

  48. for(int i=0;i<10;i++){  

  49.            HashMap<String, Object> tempHashMap = new HashMap<String, Object>();  

  50.            tempHashMap.put("p_w_picpath", R.drawable.icon);  

  51.            tempHashMap.put("title", "标题"+i);  

  52.            tempHashMap.put("info", "描述性信息");  

  53.            arrayList.add(tempHashMap);  

  54.        }  

  55. return arrayList;  

  56.    }  

  57. @Override

  58. protectedvoid onListItemClick(ListView l, View v, int position, long id) {  

  59.        Log.i("输出信息",v.toString() );  

  60.    }  

  61. }  


zujian.java


[java] view plain copy
  1. package cn.com.android2.listview;  

  2. import android.widget.Button;  

  3. import android.widget.ImageView;  

  4. import android.widget.TextView;  

  5. publicfinalclass ZuJian {  

  6. public ImageView p_w_picpathView;  

  7. public TextView titleView;  

  8. public TextView infoView;  

  9. public Button button;  

  10. }  


MyAdapter.java


[java] view plain copy
  1. package cn.com.android2.listview;  

  2. import java.util.ArrayList;  

  3. import java.util.HashMap;  

  4. import android.app.AlertDialog;  

  5. import android.content.Context;  

  6. import android.content.DialogInterface;  

  7. import android.view.LayoutInflater;  

  8. import android.view.View;  

  9. import android.view.ViewGroup;  

  10. import android.view.View.OnClickListener;  

  11. import android.widget.BaseAdapter;  

  12. import android.widget.Button;  

  13. import android.widget.ImageView;  

  14. import android.widget.TextView;  

  15. /**

  16. * @author chenzheng_java

  17. * @description 该类的部分实现模仿了SimpleAdapter

  18. */

  19. publicclass MyAdapter extends BaseAdapter {  

  20. private ArrayList<HashMap<String, Object>> data;  

  21. /**

  22.     * LayoutInflater 类是代码实现中获取布局文件的主要形式

  23.     *LayoutInflater layoutInflater = LayoutInflater.from(context);

  24.     *View convertView = layoutInflater.inflate();

  25.     *LayoutInflater的使用,在实际开发种LayoutInflater这个类还是非常有用的,它的作用类似于 findViewById(),

  26.    不同点是LayoutInflater是用来找layout下xml布局文件,并且实例化!

  27.    而findViewById()是找具体xml下的具体 widget控件(如:Button,TextView等)。

  28.     */

  29. private LayoutInflater layoutInflater;  

  30. private Context context;  

  31. public MyAdapter(Context context,ArrayList<HashMap<String, Object>> data) {  

  32. this.context = context;  

  33. this.data = data;  

  34. this.layoutInflater = LayoutInflater.from(context);  

  35.    }  

  36. /**

  37.     *获取列数

  38.     */

  39. publicint getCount() {  

  40. return data.size();  

  41.    }  

  42. /**

  43.     *获取某一位置的数据

  44.     */

  45. public Object getItem(int position) {  

  46. return data.get(position);  

  47.    }  

  48. /**

  49.     *获取唯一标识

  50.     */

  51. publiclong getItemId(int position) {  

  52. return position;  

  53.    }  

  54. /**

  55.     * android绘制每一列的时候,都会调用这个方法

  56.     */

  57. public View getView(int position, View convertView, ViewGroup parent) {  

  58.        ZuJian zuJian = null;  

  59. if(convertView==null){  

  60.            zuJian = new ZuJian();  

  61. // 获取组件布局

  62.            convertView = layoutInflater.inflate(R.layout.vlist2, null);  

  63.            zuJian.p_w_picpathView = (ImageView) convertView.findViewById(R.id.p_w_picpath);  

  64.            zuJian.titleView = (TextView) convertView.findViewById(R.id.title);  

  65.            zuJian.infoView = (TextView) convertView.findViewById(R.id.info);  

  66.            zuJian.button = (Button) convertView.findViewById(R.id.view_btn);  

  67. // 这里要注意,是使用的tag来存储数据的。

  68.            convertView.setTag(zuJian);  

  69.        }  

  70. else {  

  71.            zuJian = (ZuJian) convertView.getTag();  

  72.        }  

  73. // 绑定数据、以及事件触发

  74.        zuJian.p_w_picpathView.setBackgroundResource((Integer) data.get(position).get("p_w_picpath"));  

  75.        zuJian.titleView.setText((String)data.get(position).get("title"));  

  76.        zuJian.infoView.setText((String)data.get(position).get("info"));  

  77.        zuJian.button.setOnClickListener(new OnClickListener(){  

  78. publicvoid onClick(View v) {  

  79.                showInfo();  

  80.            }  

  81.        });  

  82. return convertView;  

  83.    }  

  84. /**

  85.     *当用户点击按钮时触发的事件,会弹出一个确认对话框

  86.     */

  87. publicvoid showInfo(){    

  88. new AlertDialog.Builder(context)    

  89.                 .setTitle("我的listview")    

  90.                .setMessage("介绍...")    

  91.                .setPositiveButton("确定", new DialogInterface.OnClickListener() {    

  92. publicvoid onClick(DialogInterface dialog, int which) {    

  93.                     }    

  94.                 })    

  95.               .show();    

  96.            }    

  97. }  


废话连篇:


代码中的注释已经解释的很清楚了,这里再次强调一遍,三步骤

第一步:准备主布局文件、组件布局文件等

第二步:获取并整理数据

第三部:绑定数据,这里我们是通过自己编写adapter来完成的。


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了。