聲明:博文為原創,文章內容為,效果展示,思路闡述,及代碼片段。
轉載請保留原文出處“http://my.oschina.net/gluoyer/blog”,謝謝!
您可以到博客的“友情鏈接”中,“程序猿媛(最新下載)*.*”下載最新版本,持續更新!當前版本,也可直接點擊“當前1.5版本”下載。
引子:自定義ListView的Adapter,給Item中的子控件(按鈕、圖標、文字等)添加點擊事件,來進行點擊后的不同處理,是經常要做的事情。但有些需要在處理事件中,對Activity中其他控件進行更新的話,通常把Adapter在Activity中實現,處理比較多的話,在Activity中增加幾百行代碼還是比較普遍的情況。 我的習慣,還是把Adapter獨立出來。那么,其他控件的更新如何處理呢?
當然,每個人的習慣不同,我這里只是闡述一種思路,如果您覺得有用,可以作為參考;其他就麻煩繞道吧。
首先,還是看下實現效果吧:
本文介紹:
主要是通過Handler管理Message的方式,在Adapter處理點擊事件時,將所需數據傳送回所屬Activity。在Activity中處理點擊事件的后續操作的同時,又將Adapter獨立了出來,代碼結構就比較清晰,便於閱讀和管理了。
Adapter的重寫,主要處理集中在getView方法中,這個想必大家都比較了解了,不贅述,請參見源代碼,代碼目錄結構如下:
功能的實現比較簡單,主要是一種方式,主要兩部分:
一、在LiChildClickActivity中為LiccAdapter設置Handler
首先,在Activity中定義Handler,用於接收點擊事件返回的值:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
private
Handler mHandle =
new
Handler() {
@Override
public
void
handleMessage(Message msg) {
LiData data = (LiData) msg.getData().getSerializable(LiccAdapter.BUNDLE_KEY_LIDATA);
switch
(msg.what) {
case
LiccAdapter.CLICK_INDEX_ITEM:
onItemClicked(msg.arg1, data);
break
;
case
LiccAdapter.CLICK_INDEX_COUNTRY:
onCountryClicked(data);
break
;
case
LiccAdapter.CLICK_INDEX_NAME:
onNameClicked(data);
break
;
}
}
};
|
其次,為ListView設置帶有mHandle的LiccAdapter:
1
2
3
4
5
6
7
8
9
|
// 獲取ListView
ListView lv = (ListView) findViewById(R.id.licc_list);
// 創建數據列表
ArrayList<LiData> list =
new
ArrayList<LiData>();
/**
填充列表數據代碼,請查看源碼 */
// 為列表設置帶mHandle參數的LiccAdapter
LiccAdapter adapter =
new
LiccAdapter(
this
, mHandle, list);
lv.setAdapter(adapter);
|
這樣,在LiccAdapter中,處理點擊事件時發送的消息,就可以在handleMessage中接收,並處理了。而且,onNameClicked等方法中,涉及到Activity中包含的一些成員,或布局中的其他控件時,就不用擔心,在LiccAdapter中無法調用了。
二、在LiccAdapter中設置點擊事件,並通過Message將數據回傳
首先,定義一些成員變量及靜態變量,保存數據,對應狀態:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
private
Context context;
// 點擊索引:點擊列表項;點擊按鈕;點擊名字。
protected
final
static
int
CLICK_INDEX_ITEM =
0
;
protected
final
static
int
CLICK_INDEX_COUNTRY =
1
;
protected
final
static
int
CLICK_INDEX_NAME =
2
;
// 記錄數據列表
private
ArrayList<LiData> list;
// 記錄Activity中接受消息的Handler
private
Handler mHandle;
// 關鍵字
protected
final
static
String BUNDLE_KEY_LIDATA =
"lidata"
;
// 構造方法
public
LiccAdapter(Context context, Handler handle, ArrayList<LiData> list) {
this
.context = context;
mHandle = handle;
this
.list =
new
ArrayList<LiData>();
for
(LiData data : list) {
this
.list.add(data);
}
}
|
其次,自定義點擊事件監聽器:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
private
class
OnItemChildClickListener
implements
View.OnClickListener {
// 點擊類型索引,對應前面的CLICK_INDEX_xxx
private
int
clickIndex;
// 點擊列表位置
private
int
position;
public
OnItemChildClickListener(
int
clickIndex,
int
position) {
this
.clickIndex = clickIndex;
this
.position = position;
}
@Override
public
void
onClick(View v) {
// 創建Message並填充數據,通過mHandle聯系Activity接收處理
Message msg =
new
Message();
msg.what = clickIndex;
msg.arg1 = position;
Bundle b =
new
Bundle();
b.putSerializable(BUNDLE_KEY_LIDATA, list.get(position));
msg.setData(b);
mHandle.sendMessage(msg);
}
}
|
最后,在重寫的getView中,為各個子元素設置監聽即可:
1
2
3
4
5
6
7
8
9
10
|
// 這個holder,您懂的吧。
// 為按鈕設置點擊事件監聽
holder.mCountry.setOnClickListener(
new
OnItemChildClickListener(CLICK_INDEX_COUNTRY, position));
// 為名字設置點擊事件監聽
holder.mName.setOnClickListener(
new
OnItemChildClickListener(CLICK_INDEX_NAME, position));
// 設置列表項的監聽事件
convertView.setOnClickListener(
new
OnItemChildClickListener(CLICK_INDEX_ITEM, position));
|
Ok,如此,點擊列表項,及其設置了點擊監聽事件的子控件,就可以將帶着數據的消息傳回Activity了。
當然,這里看不出什么優勢,完全可以把LiccAdapter放到Activity里面實現。但實際應用中,有些Activity需要處理的事情還是比較多的,Adapter比較復雜的話,代碼量也是有一些的。
打個比方,一個2000行代碼的Activity,包含兩個各自500行代碼的自定義Adapter,如果剝離出來,Activity的代碼行數一下減少了接近一半,整體代碼閱讀起來,還是會舒服一些的吧。