转自http://www.cnblogs.com/carmanloneliness/archive/2012/02/27/2370597.html
ListView由复杂到简单
项目做完了,其中用到的ListView控件很大,有自由的时间就总结一下ListView的各个知识点。谈到ListView总是离不开adapter的使用,在这片文章中也总结下adapter的使用,主要讲述两个adapter吧,baseadapter和cursoradapter的使用。这俩是使用频率最多的adapter。当然还有用系统的adapter,但这个较简单。到文章最后再举几个更复杂的ListView的例子,作为扩展内容。
一.在xmlListView应设置为
<ListView android:id="@+id/list_goods"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />。主要就是宽度填满,高度自适应。
还有很多很实用的属性:
android:cacheColorHint="#00000000" :ListView上下拖动的时候会出现黑框,如下图所示。设置左边的属性就可完美解决,当然在代码中也设置该属性(不推荐).
android:divider="#000000" 该属性是用来设置ListView 间隔线 的颜色。很实用
android:dividerHeight="1px" 用来设置 间隔线 的高度,要设置的话一般就是1px,能看出来颜色就OK啦。
Android中有很多xml属性可以完美解决的事情,譬如在manifest文件的activity标签中设置android:theme="@android:style/Theme.NoTitleBar",就可隐藏标题。希望读者多研究研究这一点,最好不要在Java代码里面实现这些功能。
二:绑定继承自BaseAdapter的的ListView
第一次使用自定义adapter理解起来有点复杂,因为继承的方法太多,其中最主要的就是getView方法。多联系就熟悉啦。自定义adapter的目的无非以下几点:
ListView中实现按钮的监听:
要有漂亮图片的显示;
复选框等复杂控件的显示;
需求较复杂,系统自带的adapter满足不了要求。
结合最常用的上述几点要求,弄一个综合的ListView例子来讲述下这些功能的实现。
效果如下图:
这个例子里实现了图片显示,复选框,按钮。共用了五个控件,一个ImageView(imageItem),两个TextView(titleItem,infoItem),一个CheckBox(checkItem),一个Button(detailItem)。在这里详细说明下如何定义adapter,Demo的代码放在附件代码里供下载吧。
public ListViewAdapter(Context context, List<Map<String, Object>> listItems) {
this.listItems = listItems;
XXXXXXX
}
构造放在的作用是传入一个listItems,listItems是ListView容器中各个控件显示的内容,imageItem要显示的图片,titleItem和infoItem要显示的文字以及点击detailItem弹出对话所显示的文字,在定义adapter时调用构造方法将设置好的变量传入adapter当中来,这样就有内容。接下来就依次介绍下实现BaseAdapter所必须继承的方法。
1.@Override
public int getCount() {
// TODO Auto-generated method stub
return listItems.size();
}
这个是ListView中所包含的Item的数量。既然数据都在listItems中,那么这里就返回listItems的长度。
2.@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return null;
}
这里可以return null.但更专业一点返回listItems.get(position),这样在getView函数中直接调用getItem(int XX)方法就行了,不用再调用具体的值,更好的提现了封装性;
3.@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
和2中同样的道理,可以return 0,也可以return position.
4.这个ListView中共有5个控件,控件较多,要定义一个final类型的内部类,来封装这些控件,如下所示:
public final class ListItemView{ //自定义控件集合
public ImageView image;
public TextView title;
public TextView info;
public CheckBox check;
public Button detail;
}这样在getView中赋值的话直接用"变量名.类的变量"就可以了。当然也可以不用声明内部类,而用变量引用来实现。
5.最主要的就是接下来的getView方法
getView方法的参数共3个,这三个参数具体含义可查API文档,讲解的比我详细,返回值就是中间这个变量convertView,getView的方法作用简单说来就是将第二个参数赋予正确的值并且返回。这其中要注意一点要将convertView绑定4中内部类的一个变量,这才能是convertView设置为正确的格式。通过setTag的方法来实现该功能。
ListItemView listItemView = null;
if (convertView == null) {
XXXX
convertView.setTag(listItemView);
}else {
listItemView = (ListItemView)convertView.getTag();
}
若想实现ListView的单双行不同颜色显示,或者各行不同颜色显示,就要在getView方法中实现。举例,单双行不同颜色显示的方法如下:
if(position % 2 == 0)
convertView.setBackgroundColor(Color.WHITE);
else
convertView.setBackgroundColor(Color.parseColor("#F9F6F1"));
同样的功能,若是在CursorAdapter中实现,就要在newView方法里面实现,而不是在bindView里面实现。
代码附上!太晚了,就写到baseAdapter吧,cursoradapter明天写。想得挺简单的,一提笔就觉得有很多细节要交代,各位看官将就看吧,若不明,邮件给我carman_loneliness@163.com
-Carman
-2010.2.27
1 package a.b; 2 3 import java.util.List; 4 import java.util.Map; 5 import android.app.AlertDialog; 6 import android.content.Context; 7 import android.util.Log; 8 import android.view.LayoutInflater; 9 import android.view.View; 10 import android.view.ViewGroup; 11 import android.widget.BaseAdapter; 12 import android.widget.Button; 13 import android.widget.CheckBox; 14 import android.widget.CompoundButton; 15 import android.widget.ImageView; 16 import android.widget.TextView; 17 18 public class ListViewAdapter extends BaseAdapter { 19 20 private Context context; 21 private List<Map<String, Object>> listItems; 22 private LayoutInflater listContainer; 23 private boolean[] hasChecked; 24 public final class ListItemView{ 25 public ImageView image; 26 public TextView title; 27 public TextView info; 28 public CheckBox check; 29 public Button detail; 30 } 31 public ListViewAdapter(Context context, List<Map<String, Object>> listItems) { 32 this.context = context; 33 listContainer = LayoutInflater.from(context); 34 this.listItems = listItems; 35 hasChecked = new boolean[getCount()]; 36 } 37 @Override 38 public int getCount() { 40 return listItems.size(); 41 } 42 43 @Override 44 public Object getItem(int position) { 45 46 return null; 47 } 48 49 @Override 50 public long getItemId(int position) { 51 52 return 0; 53 } 54 55 private void checkedChange(int checkedID) { 56 hasChecked[checkedID] = !hasChecked[checkedID]; 57 } 58 64 public boolean hasChecked(int checkedID) { 65 return hasChecked[checkedID]; 66 } 67 72 private void showDetailInfo(int clickID) { 73 new AlertDialog.Builder(context) 74 .setTitle("物品详情:" + listItems.get(clickID).get("info")) 75 .setMessage(listItems.get(clickID).get("detail").toString()) 76 .setPositiveButton("确定", null) 77 .show(); 78 } 79 80 @Override 81 public View getView(int position, View convertView, ViewGroup parent) { 82 83 Log.e("method", "getView"); 84 final int selectID = position; 85 86 ListItemView listItemView = null; 87 if (convertView == null) { 88 listItemView = new ListItemView(); 89 90 convertView = listContainer.inflate(R.layout.list_item, null); 91 92 listItemView.image = (ImageView)convertView.findViewById(R.id.imageItem); 93 listItemView.title = (TextView)convertView.findViewById(R.id.titleItem); 94 listItemView.info = (TextView)convertView.findViewById(R.id.infoItem); 95 listItemView.detail= (Button)convertView.findViewById(R.id.detailItem); 96 listItemView.check = (CheckBox)convertView.findViewById(R.id.checkItem); 97 98 convertView.setTag(listItemView); 99 }else { 100 listItemView = (ListItemView)convertView.getTag(); 101 } 102 106 listItemView.image.setBackgroundResource((Integer) listItems.get( 107 position).get("image")); 108 listItemView.title.setText((String) listItems.get(position) 109 .get("title")); 110 listItemView.info.setText((String) listItems.get(position).get("info")); 111 listItemView.detail.setText("商品详情"); 112 113 listItemView.detail.setOnClickListener(new View.OnClickListener() { 114 @Override 115 public void onClick(View v) { 116 117 showDetailInfo(selectID); 118 } 119 }); 120 121 listItemView.check 122 .setOnCheckedChangeListener(new CheckBox.OnCheckedChangeListener() { 123 @Override 124 public void onCheckedChanged(CompoundButton buttonView, 125 boolean isChecked) { 126 127 checkedChange(selectID); 128 } 129 }); 130 131 return convertView; 132 } 133 }