【Android】ListView與Button的共存問題解決
- 首先,說明一下,ListView中每一行包括以下三項:
- res/layout/main.xml
|
因為繼承了ListActivity,所以ListView 的id設定為"@id/android:list"是必須的
- res/layout/lvitem.xml
注意:
在< RelativeLayout>中
android:descendantFocusability= "blocksDescendants"
和< ImageButton>中
android:focusable = "false"
這兩項的設定很關鍵,如果不設定,將導致ListView的ItemClick事件將無法觸發,該事件被ImageButton的click事件遮蔽了。
|
- 接下來,我們看看繼承ListActivity的實現
在lvWithButtonExt中,為了能處理ImageButton的click事件,我繼承了BaseAdapter類,並重新實現了getView()介面,在其中加入了Button的clicklistener,詳見 lvButtonAdapter類的實現。
|
- 接下來,我們看看lvButtonAdapter 的實現
為了響應按鈕的點選事件,首先要記錄按鈕的位置,然後為按鈕設定clicklistener。
在重新實現的getView()介面中,我使用了lvButtonListener監聽類,在建構函式中,記錄行號,以便在OnClick介面中能準確的定位按鈕所在的位置,進而對相應的行進行處理。
public
class
lvButtonAdapter extends
BaseAdapter {
private
class
buttonViewHolder {
ImageView
appIcon;
TextView appName;
ImageButton buttonClose;
}
private
ArrayList
<
HashMap
<
String
,
Object
>
>
mAppList;
private
LayoutInflater mInflater;
private
Context
mContext;
private
String
[
]
keyString;
private
int
[
]
valueViewID;
private
buttonViewHolder holder;
public
lvButtonAdapter(
Context
c,
ArrayList
<
HashMap
<
String
,
Object
>
>
appList,
int
resource,
String
[
]
from
,
int
[
]
to)
{
mAppList =
appList;
mContext =
c;
mInflater =
(
LayoutInflater)
mContext.
getSystemService(
Context
.
LAYOUT_INFLATER_SERVICE)
;
keyString =
new
String
[
from
.
length
]
;
valueViewID =
new
int
[
to.
length
]
;
System
.
arraycopy
(
from
,
0,
keyString,
0,
from
.
length
)
;
System
.
arraycopy
(
to,
0,
valueViewID,
0,
to.
length
)
;
}
@Override
public
int
getCount
(
)
{
return
mAppList.
size
(
)
;
}
@Override
public
Object
getItem
(
int
position
)
{
return
mAppList.
get
(
position
)
;
}
@Override
public
long
getItemId(
int
position
)
{
return
position
;
}
public
void
removeItem
(
int
position
)
{
mAppList.
remove
(
position
)
;
this
.
notifyDataSetChanged(
)
;
}
@Override
public
View
getView
(
int
position
,
View
convertView,
ViewGroup parent
)
{
if
(
convertView !
=
null
)
{
holder =
(
buttonViewHolder)
convertView.
getTag
(
)
;
}
else
{
convertView =
mInflater.
inflate
(
R.
layout
.
lvitem,
null
)
;
holder =
new
buttonViewHolder(
)
;
holder.
appIcon =
(
ImageView
)
convertView.
findViewById(
valueViewID[
0]
)
;
holder.
appName =
(
TextView)
convertView.
findViewById(
valueViewID[
1]
)
;
holder.
buttonClose =
(
ImageButton)
convertView.
findViewById(
valueViewID[
2]
)
;
convertView.
setTag(
holder)
;
}
HashMap
<
String
,
Object
>
appInfo =
mAppList.
get
(
position
)
;
if
(
appInfo !
=
null
)
{
String
aname =
(
String
)
appInfo.
get
(
keyString[
1]
)
;
int
mid =
(
Integer
)
appInfo.
get
(
keyString[
0]
)
;
int
bid =
(
Integer
)
appInfo.
get
(
keyString[
2]
)
;
holder.
appName.
setText
(
aname)
;
holder.
appIcon.
setImageDrawable(
holder.
appIcon.
getResources
(
)
.
getDrawable(
mid)
)
;
holder.
buttonClose.
setImageDrawable(
holder.
buttonClose.
getResources
(
)
.
getDrawable(
bid)
)
;
holder.
buttonClose.
setOnClickListener(
new
lvButtonListener(
position
)
)
;
}
return
convertView;
}
class
lvButtonListener implements
OnClickListener {
private
int
position
;
lvButtonListener(
int
pos)
{
position
=
pos;
}
@Override
public
void
onClick(
View
v)
{
int
vid=
v.
getId
(
)
;
if
(
vid =
=
holder.
buttonClose.
getId
(
)
)
removeItem
(
position
)
;
}
}
}
////////////////////////////////////////
備註1; 對於Android開發來說處理一些介面需要和Adapter介面卡打交道,雖然Android自帶了一些比如ArrayAdapter但是大多數情況下無法滿足我們需要,所以就要從BaseAdapter派生一個類滿足我們特殊的需要。
首先我們可能重寫getView(),通過LayoutInflater的inflate方法對映一個自己定義的Layout佈局xml載入或從xxxView中建立。這些大家可能滾瓜爛熟了但是仍然很多Android 開發者對於BaseAdapter中notifyDataSetChanged()方法不是很理解,notifyDataSetChanged方法通過一個外部的方法控制如果介面卡的內容改變時需要強制呼叫getView來重新整理每個Item的內容。
http://blogimg.chinaunix.net/blog/upfile2/101203142001.jpg