`
aswang
  • 浏览: 847806 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

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以后,问题又出现了!

 

分享到:
评论
2 楼 aswang 2012-04-20  
wangbeyond6 写道
碰到 同样的 问题.


貌似通过ContentProvider来处理数据的变化可以解决,但是暂时没时间去测试这个!
1 楼 wangbeyond6 2012-04-20  
碰到 同样的 问题.

相关推荐

    android listview单击事件

    在Android开发中,ListView是应用最广泛的视图组件之一,尤其在展示大量数据时,它以列表形式高效地展示信息。本教程将深入探讨ListView的单击事件处理,以及如何在实际项目中实现这一功能。 首先,理解ListView的...

    android 自定义listview无法响应点击事件OnItemClickListener

    以上是关于“android 自定义listview无法响应点击事件OnItemClickListener”这一问题的详细分析和解决策略。在实际开发中,遇到此类问题,可以根据这些点逐一排查,通常能够找到问题所在并解决。对于Test2这个压缩包...

    在Activity中响应ListView内部按钮的点击事件

    本篇文章将详细讲解如何在Activity中响应ListView内部按钮的点击事件,主要涉及的知识点包括:接口回调、ListView的适配器(Adapter)机制以及事件处理。 首先,我们理解ListView的工作原理。ListView通过Adapter将...

    android ListView和ScrollView事件冲突

    这通常会导致ListView无法正确响应用户的滑动操作,因为它无法接收到应有的滑动事件。 解决这个问题有几种常见的方法: 1. **使用 NestedScrollView 替换 ScrollView**: Android提供了NestedScrollView,它是...

    androidListView下拉刷新Demo

    总结,"androidListView下拉刷新Demo"是一个典型的Android开发实践,涉及到Android UI组件的交互、事件监听、数据加载以及第三方库的使用。通过这样的示例,开发者可以学习如何增强ListView的功能,提供更优的用户...

    Android ListView 固定列头源码

    总之,实现Android ListView固定列头是一个涉及布局设计、事件处理和自定义组件的综合任务。`HLListView`源码提供了实现这一功能的具体实现细节,可以帮助开发者更好地理解和应用这一技术。通过深入研究和实践,...

    android listView 模拟物理分页Demo 按键

    在Android开发中,ListView是一种常用的组件,用于展示大量的数据列表。在这个"android listView 模拟物理分页Demo 按键"项目中,开发者通过按键实现了分页加载数据的功能,以便用户逐步查看大量内容,避免一次性...

    android Listview demo

    在Android开发中,ListView是一个非常重要的组件,它用于展示大量数据集合,并且支持滚动操作。本教程通过一个名为"ListApp"的示例项目,详细介绍了如何在Android中使用ListView来构建用户界面并实现基本的功能。 ...

    android listView 分页加载

    在Android开发中,ListView是一种常用的组件,用于展示大量的数据列表。分页加载是优化ListView性能、提高用户体验的重要技术。本文将深入探讨“Android ListView的分页加载”这一主题,包括其原理、实现方法以及...

    android listView

    标题“android listView”直指Android开发中的ListView组件,这是Android SDK提供的一种可以显示大量数据的滚动视图。ListView通过将数据绑定到多个列表项视图(也称为ViewHolder)来实现高效渲染。每个列表项视图都...

    android listview+fragment实现仿京东分类

    在这个"android listview+fragment实现仿京东分类"项目中,我们将探讨如何利用这两种组件来模仿京东应用中的商品分类功能。以下是相关知识点的详细说明: 1. **ListView**: ListView是Android SDK提供的一种视图...

    android listview 下拉回弹刷新效果

    SwipeRefreshLayout是Android Support Library中的一个组件,它为子View(如ListView)提供了下拉刷新的功能。使用SwipeRefreshLayout,只需要将ListView作为其子View,设置相应的刷新监听器,即可实现下拉刷新效果...

    android中一个简单的LIstView用法例子

    在Android开发中,ListView是一个非常重要的组件,它用于展示大量数据列表,通常用于实现滚动效果。这个简单的ListView用法例子将帮助初学者理解和掌握如何在实际项目中运用ListView。 首先,我们来了解一下...

    Android ListView 实现分批加载

    在Android开发中,ListView是一种常用的组件,用于展示大量的数据列表。由于一次性加载所有数据可能会消耗大量内存并导致应用性能下降,因此通常会采用分批加载(也称为懒加载)策略来优化用户体验。本文将深入探讨...

    Android listview和宫格list切换

    在Android开发中,ListView和GridView(宫格ListView)是两种常用的布局组件,它们都被广泛用于显示大量的数据项。本项目“Android listview和宫格list切换”提供了一种实现这两种视图之间平滑切换的方法,并且包含...

    Android ListView动态查询更新代码

    在Android开发中,ListView是一种常用的组件,用于展示大量的列表数据。动态查询和更新ListView是提高用户体验的关键技术,尤其是在处理大量数据流或者实时更新信息时。本文将深入探讨如何实现Android ListView的...

    android 一些listview例子

    在Android开发中,ListView是一个非常重要的组件,它用于展示大量数据集合,并且支持滚动操作。在"android 一些listview例子"这个主题中,我们将会深入探讨ListView的各种使用方法和优化策略。 首先,ListView的...

    android中在Activity中响应ListView内部按钮的点击事件的两种方法

    在Android开发中,ListView是一种常用的组件,用于展示可滚动的列表数据。然而,当ListView的item内部包含有按钮等交互元素时,我们可能需要监听这些元素的点击事件,并在Activity中进行相应的处理,而不是在Adapter...

    android listview item 拖动排序

    在Android开发中,ListView是一种常用的组件,用于展示大量的数据列表。然而,标准的ListView并不支持直接的拖放排序功能。为了实现这个特性,开发者通常会借助第三方库,如`DragSortListView`。在这个主题中,我们...

Global site tag (gtag.js) - Google Analytics