zoukankan      html  css  js  c++  java
  • Android ListView内部组件事件响应

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


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

    Xml代码 复制代码 收藏代码
    1. android:focusable="false" 

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

    Xml代码 复制代码 收藏代码
    1. android:descendantFocusability="blocksDescendants" 

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

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

    Java代码 复制代码 收藏代码
    1. private class DownloadListAdapter extends BaseAdapter{ 
    2.         private Context mContext; 
    3.         private LayoutInflater inflater; 
    4.         private List<Download> data; 
    5.         private int resource; 
    6.          
    7.         public DownloadListAdapter(Context context, 
    8.                 List<Download> data, int resource) { 
    9.             super(); 
    10.             mContext = context; 
    11.             inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
    12.             this.data = data; 
    13.             this.resource = resource; 
    14.         } 
    15.          
    16.         @Override 
    17.         public int getCount() { 
    18.             return data.size(); 
    19.         } 
    20.          
    21.         @Override 
    22.         public Object getItem(int position) { 
    23.             if(position < data.size()){ 
    24.                 return data.get(position); 
    25.             } 
    26.             return null
    27.         } 
    28.          
    29.         @Override 
    30.         public long getItemId(int position) { 
    31.             return position; 
    32.         } 
    33.          
    34.         @Override 
    35.         public View getView(int position, View convertView, ViewGroup parent){ 
    36.             final Download down = (Download)getItem(position); 
    37.             if(convertView == null){ 
    38.                 convertView = inflater.inflate(resource, parent,false); 
    39.                  
    40.                 ImageButton btn = (ImageButton)convertView.findViewById(R.id.down_pause); 
    41.                 //添加事件监听 
    42.                 btn.setOnClickListener(new OnClickListener() { 
    43.                     @Override 
    44.                     public void onClick(View v) { 
    45.                         Log.d(TAG,"添加事件监听:"+ v.hashCode() +" - "+down.getId()); 
    46.                         if(down.getStatus() == Downloader.STATUS_RUNNING){ 
    47.                             Log.d(TAG, "暂停下载 : "+down.getId()); 
    48.                             mDownloader.pause(down.getId()); 
    49.                             down.setStatus(Downloader.STATUS_PAUSED); 
    50.                         }else if(down.getStatus() == Downloader.STATUS_PAUSED){ 
    51.                             Log.d(TAG, "继续下载 : "+down.getId()); 
    52.                             mDownloader.continueDownload(down.getId()); 
    53.                             down.setStatus(Downloader.STATUS_RUNNING); 
    54.                         } 
    55.                         //DownloadListAdapter.this.notifyDataSetChanged(); 
    56.                         return
    57.                     } 
    58.                 }); 
    59.             } 
    60.             TextView nameText = (TextView)convertView.findViewById(R.id.down_name); 
    61.             ProgressBar bar = (ProgressBar)convertView.findViewById(R.id.down_progress); 
    62.             ImageButton btn = (ImageButton)convertView.findViewById(R.id.down_pause); 
    63.              
    64.             int progress = (int)(down.getDownloadSize()*100/down.getSize()); 
    65.             String name = down.getName(); 
    66.              
    67.             nameText.setText(name); 
    68.             bar.setProgress(progress); 
    69.             Log.d(TAG, "状态:"+down.getStatus()); 
    70.              
    71.             return convertView; 
    72.         } 

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

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

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

    Java代码 复制代码 收藏代码
    1. @Override 
    2.         public View getView(int position, View convertView, ViewGroup parent){ 
    3.             final Download down = (Download)getItem(position); 
    4.             Holder holder = null
    5.             if(convertView == null){ 
    6.                 convertView = inflater.inflate(resource, parent,false); 
    7.                  
    8.                 holder = new Holder(); 
    9.                 holder.text = (TextView)convertView.findViewById(R.id.down_name); 
    10.                 holder.bar = (ProgressBar)convertView.findViewById(R.id.down_progress); 
    11.                 holder.imageBtn = (ImageButton)convertView.findViewById(R.id.down_pause); 
    12.                  
    13.                 convertView.setTag(holder); 
    14.                  
    15.                 //添加事件监听 
    16.                 holder.imageBtn.setOnClickListener(new OnClickListener() { 
    17.                     @Override 
    18.                     public void onClick(View v) { 
    19.                         Log.d(TAG,"添加事件监听:"+ v.hashCode() +" - "+down.getId()); 
    20.                         if(down.getStatus() == Downloader.STATUS_RUNNING){ 
    21.                             Log.d(TAG, "暂停下载 : "+down.getId()); 
    22.                             mDownloader.pause(down.getId()); 
    23.                             down.setStatus(Downloader.STATUS_PAUSED); 
    24.                         }else if(down.getStatus() == Downloader.STATUS_PAUSED){ 
    25.                             Log.d(TAG, "继续下载 : "+down.getId()); 
    26.                             mDownloader.continueDownload(down.getId()); 
    27.                             down.setStatus(Downloader.STATUS_RUNNING); 
    28.                         } 
    29.                         //DownloadListAdapter.this.notifyDataSetChanged(); 
    30.                         return
    31.                     } 
    32.                 }); 
    33.             }else
    34.                 holder = (Holder)convertView.getTag(); 
    35.             } 
    36.              
    37.             int progress = (int)(down.getDownloadSize()*100/down.getSize()); 
    38.             String name = down.getName(); 
    39.              
    40.             holder.text.setText(name); 
    41.             holder.bar.setProgress(progress); 
    42.             Log.d(TAG, "状态:"+down.getStatus()); 
    43.  
    44.              
    45.             return convertView; 
    46.         } 

    Holder定义如下:

    Java代码 复制代码 收藏代码
    1. class Holder { 
    2.             public TextView text; 
    3.             public ImageButton imageBtn; 
    4.             public ProgressBar bar; 
    5.         } 

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

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

    转自:http://aswang.iteye.com/blog/1490245

  • 相关阅读:
    使用window.showModalDialog的一个问题
    ASP.NET 的<system.codedom>标签
    SqlServer事务中的可重复读和序列化隔离界别
    C#使用163的SMTP服务器发送邮件
    在HTML中小心使用空格和回车
    ASP.NET 4.0的ClientIDMode属性
    C/C++中判断某一文件或目录是否存在<转>
    新公司工作有感
    网络编程(转)<下>
    VC控件ListControl的使用
  • 原文地址:https://www.cnblogs.com/bmate/p/2674003.html
Copyright © 2011-2022 走看看