论坛首页 移动开发技术论坛

CheckBox在ListView 而导致其OnItemClickListener不会被触发

浏览 14533 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2010-06-22   最后修改:2010-06-22

CheckBox在ListView 而导致其OnItemClickListener不会被触发

 

 

这个标题实在有点长  没办法而为之 本人语言实在乏善可陈   故开题之前 重新描述之

 

写道
ListView 中的各个item 通过 extends BaseAdapter 可以显示任意子View 当然也包括CheckBox

但是 当使用CheckBox 会导致ListView.setOnItemClickListener(OnItemClickListener listener) 中的listener不会被回调

 

 

通过Google 得到以下解释:

 

写道
ListView的item中加入CheckBox后 导致ListView对OnItemClick事件无法响应 原因是因为CheckBox的事件响应优先级高于List Item,所以屏蔽了ListItem的单击事件

 

 

而解决办法是:

 

写道
设置CheckBox的android:focusable="false"即可

 

 

 

但是 我设置以后 依然无效  只能再想别的办法   以下即为步骤:

 

 

 

[代码 步骤]

 

 

1. 鉴于今天重点以ListView 响应OnItemClickListener   故打算其显示item 数据以联系人数据为例

 

- 查询目标Uri

 

cursor = getContentResolver().query(People.CONTENT_URI, 
                null, null, null, null);

 

- 定义PeopleAdapter 用于接收数据源Cursor 

 

public class PeopleAdapter extends BaseAdapter {
    	Activity activity;
    	
    	public PeopleAdapter(Activity a){
    		activity = a;
    	}
    	
		@Override
		public int getCount() {
			// TODO Auto-generated method stub
			return cursor.getCount();
		}

		@Override
		public Object getItem(int arg0) {
			// TODO Auto-generated method stub
			return arg0;
		}

		@Override
		public long getItemId(int arg0) {
			// TODO Auto-generated method stub
			return arg0;
		}

		@Override
		public View getView(int arg0, View arg1, ViewGroup arg2) {
			// TODO Auto-generated method stub
			return CheckTest(arg0);
		}
		
		public View CheckTest(int position){
			cursor.moveToPosition(position);
			String name = cursor.getString(cursor.getColumnIndex("name"));
			
			CheckBox cb = new CheckBox(activity);
			cb.setText(name);
			cb.setFocusable(false);
			
			return cb;
		}

    }

 

 

 

 2.  emulator 运行截图

 

 

 

 

 

 

3.  通过ListView.setOnItemClickListener(...) 监听 onItemClick()  但是会失效

 

lv.setOnItemClickListener(new OnItemClickListener(){

			@Override
			public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
					long arg3) {
				// TODO Auto-generated method stub
				Log.d("TAG","onItemClick id:"+arg2);
			}
        	
        });

 

 

 

4.   下面就涉及 如何解决

 

写道
正式开始之前 说说其实现原理:

CheckBox 与 ListView.onItemClick() 冲突原因 前面说过 因为优先级问题

那么如果二者所占用的区域不同呢? 即:

CheckBox 的区域 就是 CheckBox 本身

而ListView.onItemClick() 监听 可以通过如下:


把CheckBox 放入LinearLayout , 如果单击区域是属于CheckBox 那显然就会执行CheckBox默认行为 即置CheckBox true/false , 如果单击区域处于CheckBox 外 但又属于LinearLayout 那么就视该动作 为ListView.onItemClick()

 

 

5.  定义2个int变量 作为CheckBox LinearLayout 的 id 索引起点

 

public final int LAYOUT_INDEX = 0;
public final int CHECKBOX_INDEX = 100;

 

 

 

6.  定义ListView 中 item 的布局 并设立CheckBox LinearLayout 的监听器

 

public View fromLayout(int position){
			cursor.moveToPosition(position);
			String name = cursor.getString(cursor.getColumnIndex("name"));

			final LinearLayout layout = new LinearLayout(activity);
	        layout.setOrientation(LinearLayout.HORIZONTAL);
	        layout.setId(position+LAYOUT_INDEX);
	        
			final CheckBox cb = new CheckBox(activity);
			cb.setText(name);
			cb.setBackgroundColor(Color.GRAY);
			
			cb.setId(CHECKBOX_INDEX+position);

			cb.setOnCheckedChangeListener(new OnCheckedChangeListener(){

				@Override
				public void onCheckedChanged(CompoundButton arg0, boolean arg1) {
					// TODO Auto-generated method stub
					int id = cb.getId() - CHECKBOX_INDEX;
					boolean status = arg1;
					
					popMessage("CheckBox.onCheckedChanged",id);
				}
				
			});
			
			layout.addView(cb);
			
			layout.setOnClickListener(new OnClickListener(){

				@Override
				public void onClick(View arg0) {
					// TODO Auto-generated method stub
					id = arg0.getId() - LAYOUT_INDEX;
					
					popMessage("Layout.onClick",id);
				}
				
			});
			
			
			return layout;
		}

 

 

7.  在PeopleAdapter.getView(int arg0, View arg1, ViewGroup arg2) 使用 fromLayout()    其中 popMessage() 用于通知点击区域和id

 

public void popMessage(String prefix,int id){
    	String msg = "["+prefix+"].ID:"+id;
    	Toast.makeText(this,msg,Toast.LENGTH_LONG).show();
    }

  

 

8. emulator 运行截图  // 为了标记CheckBox显示区域 我用setBackgroundColor(Color.GRAY) 设定其颜色 便于观察

 

- 点击CheckBox

 

 

 

 

 

 

- 点击其他区域(非CheckBox)

 

 

 

 

 

 

鉴于语言所限 防止有人看不懂 故贴出研究代码 大家自己运行 应该就能理解之了  对了  别忘记顶贴哦!!!!!!

 

 

 

 

 

 

 

 

 

   发表时间:2010-06-23  
我来顶你.
0 请登录后投票
   发表时间:2010-06-23  
不知有没有简单点的方法呢
0 请登录后投票
   发表时间:2010-06-23  
rainsf 写道
不知有没有简单点的方法呢

目前为止 这是我发现的最简单的解决办法了
0 请登录后投票
   发表时间:2010-06-23  
gryphone 写道
rainsf 写道
不知有没有简单点的方法呢

目前为止 这是我发现的最简单的解决办法了



设置CheckBox的android:focusable="false"是可以做到的,可能是你其他的View设置有问题,
我的很多代码都是使用此方法,不管是CursorAdapter还是ListAdapter,均没问题。
0 请登录后投票
   发表时间:2010-06-24  
sinfrancis 写道
gryphone 写道
rainsf 写道
不知有没有简单点的方法呢

目前为止 这是我发现的最简单的解决办法了



设置CheckBox的android:focusable="false"是可以做到的,可能是你其他的View设置有问题,
我的很多代码都是使用此方法,不管是CursorAdapter还是ListAdapter,均没问题。

我也不知道为什么失败 我也设定了啊 

public View CheckTest(int position){   
33.            cursor.moveToPosition(position);   
34.            String name = cursor.getString(cursor.getColumnIndex("name"));   
35.               
36.            CheckBox cb = new CheckBox(activity);   
37.            cb.setText(name);   
38.            cb.setFocusable(false);   
39.               
40.            return cb;   
41.        }
0 请登录后投票
   发表时间:2010-06-29  
gryphone 写道
sinfrancis 写道
gryphone 写道
rainsf 写道
不知有没有简单点的方法呢

目前为止 这是我发现的最简单的解决办法了



设置CheckBox的android:focusable="false"是可以做到的,可能是你其他的View设置有问题,
我的很多代码都是使用此方法,不管是CursorAdapter还是ListAdapter,均没问题。

我也不知道为什么失败 我也设定了啊 

public View CheckTest(int position){   
33.            cursor.moveToPosition(position);   
34.            String name = cursor.getString(cursor.getColumnIndex("name"));   
35.               
36.            CheckBox cb = new CheckBox(activity);   
37.            cb.setText(name);   
38.            cb.setFocusable(false);   
39.               
40.            return cb;   
41.        }

==================================================================
你这样用,其实一个Item就是一个checkBox,当然设计无效了,你用Layout包含Checkbox的时候,checkbox就好用了。因为这时候checkbox不在占据一行了。
如果你使用xml文件配置这个item布局的话,通常放到某一个Layout里面,在xml文件设计android:focusable="false"是可以的。其实原理是一样的。(只是你理解有点问题,就是checkBox直接显示,就当作一行都是checkbox区域).
0 请登录后投票
   发表时间:2010-06-29  
一般这种列表中带checkbox的,我都载对象中定义一个字段。

boolean checked

onItemClick(int postiion){
   if(data.get(position).checked){
        data.get(position).checked= false;
   }else{
         data.get(position).checked = true;
     }

  adapter.notifyDateChange();

}


0 请登录后投票
   发表时间:2010-09-08  
我只看了标题
没看内容
内容太长了
最简单的办法直接把checkbox的focusable 设为false就OK了  哪那么多废话
0 请登录后投票
   发表时间:2010-09-08  
我也是用的楼主这种方法,问题已经解决了~~
0 请登录后投票
论坛首页 移动开发技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics