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 }