今天遇到了ListView中存在其他控件時,造成ListView原本可以對item的點擊事件,變得沒有用處了,所以就上網找到了這篇文章,照著修改部分code就可以達到我的要求,還不賴~
非常感謝網路上的能人,讓我能夠解決我在開發程式時的各種難題。
[轉]
这两天在捣鼓ListView widget,为了在ListView中加入Button这类的有 “点击” 事件的widget,请教了不少高手,感谢LandMark对我的认真讲解,下面把解决过程描述一下。
ListView 和 其它能触发点击事件的widget无法一起正常工作的原因是加入其它widget后,ListView的itemclick事件将无法触发,被其它widget的click事件屏蔽。
- 首先,说明一下,ListView中每一行包括以下三项:
一个ImageView, 一个TextView,一个ImageButton,依次排开。
以下是layout的内容,分为两部分:
- res/layout/main.xml
< ? xml version = "1.0" encoding = "utf-8" ? > |
因为继承了ListActivity,所以ListView 的id设置为"@id/android:list"是必须的
- res/layout/lvitem.xml
注意:
在< RelativeLayout>中
android:descendantFocusability= "blocksDescendants"
和< ImageButton>中
android:focusable = "false"
这两项的设置很关键,如果不设置,将导致ListView的ItemClick事件将无法触发,该事件被ImageButton的click事件屏蔽了。
< ? xml version = "1.0" encoding = "utf-8" ? > |
- 接下来,我们看看继承ListActivity的实现
在lvWithButtonExt中,为了能处理ImageButton的click事件,我继承了BaseAdapter类,并重新实现了getView()接口,在其中加入了Button的clicklistener,详见 lvButtonAdapter类的实现。
public class lvWithButtonExt extends ListActivity { |
- 接下来,我们看看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