Android ListView内部组件事件响应

 


最近项目需要实现一个下载模块,界面布局就采用常见的ListView方式,实现的界面效果:


 

可是在事件监听的过程中出现问题了,内部组件如Button无法捕获到点击事件OnClick : 这个问题还好解决,通过给Button设定

 

android:focusable="false"

 然后给ListView的item布局文件的最顶层组件添加:

 

android:descendantFocusability="blocksDescendants"

 这样就可以同时相应Button的点击事件和Item的点击事件了。

 

但是,在点击后面的下载按钮时,会出现同时有两个按钮状态发生变化,ListView的Adapter的代码如下:

 

private class DownloadListAdapter extends BaseAdapter{
		private Context mContext;
		private LayoutInflater inflater;
		private List<Download> data;
		private int resource;
		
		public DownloadListAdapter(Context context,
				List<Download> data, int resource) {
			super();
			mContext = context;
			inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
			this.data = data;
			this.resource = resource;
		}
		
		@Override
		public int getCount() {
			return data.size();
		}
		
		@Override
		public Object getItem(int position) {
			if(position < data.size()){
				return data.get(position);
			}
			return null;
		}
		
		@Override
		public long getItemId(int position) {
			return position;
		}
		
		@Override
		public View getView(int position, View convertView, ViewGroup parent){
			final Download down = (Download)getItem(position);
			if(convertView == null){
				convertView = inflater.inflate(resource, parent,false);
				
				ImageButton btn = (ImageButton)convertView.findViewById(R.id.down_pause);
				//添加事件监听
				btn.setOnClickListener(new OnClickListener() {
					@Override
					public void onClick(View v) {
						Log.d(TAG,"添加事件监听:"+ v.hashCode() +" - "+down.getId());
						if(down.getStatus() == Downloader.STATUS_RUNNING){
							Log.d(TAG, "暂停下载 : "+down.getId());
							mDownloader.pause(down.getId());
							down.setStatus(Downloader.STATUS_PAUSED);
						}else if(down.getStatus() == Downloader.STATUS_PAUSED){
							Log.d(TAG, "继续下载 : "+down.getId());
							mDownloader.continueDownload(down.getId());
							down.setStatus(Downloader.STATUS_RUNNING);
						}
						//DownloadListAdapter.this.notifyDataSetChanged();
						return ;
					}
				});
			}
			TextView nameText = (TextView)convertView.findViewById(R.id.down_name);
			ProgressBar bar = (ProgressBar)convertView.findViewById(R.id.down_progress);
			ImageButton btn = (ImageButton)convertView.findViewById(R.id.down_pause);
			
			int progress = (int)(down.getDownloadSize()*100/down.getSize());
			String name = down.getName();
			
			nameText.setText(name);
			bar.setProgress(progress);
			Log.d(TAG, "状态:"+down.getStatus());
			
			return convertView;
		}
 

事件监听器是在每个Item第一次初始化的时候添加的,而且也只添加了一次,同时日志跟踪,在点击最后一个按钮的时候,OnClick里面的日志也显示只调用了一次,但是界面的上的第一个按钮的状态也跟着发生变化。

 

纠结了很久都没弄清楚到底是哪里的问题。分析可能的原因:ImageButton btn =(ImageButton)convertView.findViewById(R.id.down_pause);是通过这种方式获得,而ListView里面所有的Item都共用一个布局文件,也就是上面的所有的convertView都是通过一个布局文件构造出来的,感觉这里会发生问题,但是貌似又没问题,在添加事件监听的过程中,打印的对应组件的hashCode又是不一样的,也就是每个按钮的事件监听器都是不一样的,这样分析之后又困惑了!

 

最后改用下面的方式解决问题了,关键部分代码如下:

 

@Override
		public View getView(int position, View convertView, ViewGroup parent){
			final Download down = (Download)getItem(position);
			Holder holder = null;
			if(convertView == null){
				convertView = inflater.inflate(resource, parent,false);
				
				holder = new Holder();
				holder.text = (TextView)convertView.findViewById(R.id.down_name);
				holder.bar = (ProgressBar)convertView.findViewById(R.id.down_progress);
				holder.imageBtn = (ImageButton)convertView.findViewById(R.id.down_pause);
				
				convertView.setTag(holder);
				
				//添加事件监听
				holder.imageBtn.setOnClickListener(new OnClickListener() {
					@Override
					public void onClick(View v) {
						Log.d(TAG,"添加事件监听:"+ v.hashCode() +" - "+down.getId());
						if(down.getStatus() == Downloader.STATUS_RUNNING){
							Log.d(TAG, "暂停下载 : "+down.getId());
							mDownloader.pause(down.getId());
							down.setStatus(Downloader.STATUS_PAUSED);
						}else if(down.getStatus() == Downloader.STATUS_PAUSED){
							Log.d(TAG, "继续下载 : "+down.getId());
							mDownloader.continueDownload(down.getId());
							down.setStatus(Downloader.STATUS_RUNNING);
						}
						//DownloadListAdapter.this.notifyDataSetChanged();
						return ;
					}
				});
			}else{
				holder = (Holder)convertView.getTag();
			}
			
			int progress = (int)(down.getDownloadSize()*100/down.getSize());
			String name = down.getName();
			
			holder.text.setText(name);
			holder.bar.setProgress(progress);
			Log.d(TAG, "状态:"+down.getStatus());

			
			return convertView;
		}

  Holder定义如下:

 

class Holder {
			public TextView text;
			public ImageButton imageBtn;
			public ProgressBar bar;
		}
 

分析上面的代码,感觉没大的区别,虽然问题解决了,但是没搞懂为什么?

 

悲剧,在新插入item以后,问题又出现了!

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值