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 }