ListView与Button的共存有关问题解决
{
Button imageBtn;
Resources res = getResources();
SmsRejectClikListener mClickListener;
String [] mStrings = res.getStringArray(R.array.sms_reject);
ArrayAdapter<String> mAdapter;
public SmsRejectCallView(Context context)
{
super(context);
iniList(context);
}
public SmsRejectCallView(Context context, AttributeSet attrs)
{
super(context, attrs);
iniList(context);
}
public SmsRejectCallView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
iniList(context);
}
private void iniList(Context context)
{
setOnItemClickListener(mOnClickListener);
//Add by kylin 2011.09.23 begin
LayoutParams layoutPrams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
imageBtn = new Button(context);
imageBtn.setLayoutParams(layoutPrams);
String imageBtnName = res.getString(R.string.news_sms);
imageBtn.setText(imageBtnName);
imageBtn.setFocusable(false);
addHeaderView(imageBtn);
//end
mAdapter = new ArrayAdapter<String>(context, android.R.layout.simple_list_item_1, mStrings);
setAdapter(mAdapter);
}
private AdapterView.OnItemClickListener mOnClickListener = new AdapterView.OnItemClickListener()
{
public void onItemClick(AdapterView<?> parent, View v, int position, long id)
{
if (mClickListener == null)
{
return;
}
if (position == 0)
{
mClickListener.onClikNewSms();
}
else
{
String sms = (String)(mAdapter.getItem(position-1));
mClickListener.onClickSmsItem(sms);
}
}
};
public interface SmsRejectClikListener
{
public void onClikNewSms();
public void onClickSmsItem(String sms);
}
public void setSmsRejectSelectedListener(SmsRejectClikListener listener)
{
mClickListener = listener;
}
}
- 首先,说明一下,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的内容。