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


Android 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;}@Overridepublic int getCount() {return data.size();}@Overridepublic Object getItem(int position) {if(position < data.size()){return data.get(position);}return null;}@Overridepublic long getItemId(int position) {return position;}@Overridepublic 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() {@Overridepublic 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又是不一样的,也就是每个按钮的事件监听器都是不一样的,这样分析之后又困惑了!

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

@Overridepublic 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() {@Overridepublic 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以后,问题又出现了!

更多相关文章

  1. Android studio四大组件之Activity
  2. EditText单击触发onclick事件处理
  3. 《Android面试宝典》学习笔记(第三章:组件)
  4. android WebView组件使用总结
  5. Android系列教程之八:ListView组件的使用
  6. Android Touch事件原理加实例分析
  7. 高级组件之画廊视图

随机推荐

  1. git强制拉取代码覆盖本地的
  2. vw+rem+grid布局
  3. 关于自己理解的sort()函数中的key
  4. rem+vw布局原理和grid布局学习
  5. 流程控制之分支和循环
  6. JS初识-变量及函数
  7. 支付回调代理转发
  8. 追格知识付费小程序系统源码正式发布 一
  9. CSS伪类选择器,引入字体图标,盒模型以及em
  10. 媒体查询,固定定位,flex属性