Android开发之PullToRefresh的Click点击事件的监听实现长按删除Item

简介:

本文为原创博客,出自http://blog.csdn.net/minimicall

到今天为止,搜芽的卖家版本应该来说已经基本完成,攻坚克难的一路过来。速度也控制的比较好。

项目过程进度





从任务分配量上来看,基本还是我个人英雄主义。接下来这样不行。但暂时也没办法,师弟还需要一个学习的过程。智质不错,而且态度端正。相信搜芽买家,他就可以承担更多的开发任务了。


接下来进入正题,说我们的PullToRefresh的点击事件。其实,我是想做长按进入删除的。

见效果图。当然这个是我做出来之后的了,但做出来不容易。

效果图

先上效果图



这个时候,用户长按某个item,进入删除选中模式。


这个时候ActionBar上的菜单发生了变化,变成了一个全选和删除。


我们还可以点击ActionBar全选来选择所有Item


当然,你可以取消全选这个时候,你也可以单机某个Item取消该项。

选中了,然后按删除菜单,就是那个垃圾桶图标即可。就会删除,删除同步至服务器。

问题出先了。发现点击无效。。!

问题排查

网上很多方法。

第一个比较有用的是:http://www.tuicool.com/articles/ria6Zf


     记录下自己所犯的错误,在写ListView的点击事件时OnItemClickListener,onItemClick方法没有执行,导致ListView条目点击事件失效,检查发现百度上有很多不同的答案,但究其本质都是ListView的Item抢占焦点或者Item没有获取焦点甚至没有绑定上OnItemClickListener监听事件,而我所犯的错误是在ListView的Item布局中引入了一个Style,在Style中有一项<item name="android:clickable">true</item>,正是这一项导致所有Item都要抢占焦点,所以ListView的点击事件失效,在我去掉这一项之后ListView确实正常工作了。需要引以为戒的是,在androidl应用开发中,焦点没有获取或者其他组件抢占焦点的事情经常发生,我们可以在代码中,xml布局中,甚至Style中定义时候抢占焦点,在一般情况下,这个设置并不会造成什么异常,但我需要注意重要的组件在合适的时机必须拿到焦点,否则会产生意想不到的后果,比如我的ListView。一般组件获取焦点可以使用一下方法:

[java]    view plain  copy
  1. View.setFocusable( true ),对应xml : android:focusable= "true" .                                
  2. View.setFocusableInTouchMode( true ),对应xml : android:focusableInTouchMode= "true" .   

注意:这两个属性要同时使用。

两者的意思是让组件可以获得焦点。不过有些区别,前者执行false条件后,在执行true,还是不能获取焦点。后者执行上述过程,还是能获取焦点。  
当你加入上述代码后,在创建activity时,调用对应view的requestFocus(),(requestFocus()需要在setContentView之后执行 )这样就可以获得焦点了。当editText失去焦点了,也就不会有软键盘了 

但针对ListView还可以使用 android:descendantFocusability 属性, 下面我们来看一下 android:descendantFocusability用法简析

以下摘自: http://www.cnblogs.com/eyu8874521/archive/2012/10/17/2727882.html

        开发中很常见的一个问题,项目中的listview不仅仅是简单的文字,常常需要自己定义listview,自己的Adapter去继承BaseAdapter,在adapter中按照需求进行编写,问题就出现了,可能会发生点击每一个item的时候没有反应,无法获取的焦点。原因多半是由于在你自己定义的Item中存在诸如ImageButton,Button,CheckBox等子控件(也可以说是Button或者Checkable的子类控件),此时这些子控件会将焦点获取到,所以常常当点击item时变化的是子控件,item本身的点击没有响应。

这时候就可以使用descendantFocusability来解决啦,API描述如下:

android:descendantFocusability

Defines the relationship between the ViewGroup and its descendants when looking for a View to take focus.

Must be one of the following constant values.

该属性是当一个为view获取焦点时,定义viewGroup和其子控件两者之间的关系。

属性的值有三种:

        beforeDescendants:viewgroup会优先其子类控件而获取到焦点

        afterDescendants:viewgroup只有当其子类控件不需要获取焦点时才获取焦点

        blocksDescendants:viewgroup会覆盖子类控件而直接获得焦点

通常我们用到的是第三种,即在Item布局的根布局加上android:descendantFocusability=”blocksDescendants”的属性就好了,至此listview点击的灵异事件告一段落。心得:遇到不会不懂的地方除了网上查询资料之外,也可以多多去尝试每种属性的作用,多阅读官方文档(我始终觉得还是读原文的比翻译的理解的会更好)

第二个比较有意的是:

http://blog.csdn.net/kankankankan2222/article/details/7693190

如果ListView中的单个Item的view中存在checkbox,button等view,会导致ListView.setOnItemClickListener无效,

事件会被子View捕获到,ListView无法捕获处理该事件.

解决方法:

在checkbox、button对应的view处加android:focusable="false"
   android:clickable="false"android:focusableInTouchMode="false"

其中focusable是关键

 

OnClickListener调用getSelectedItemPosition()Click selection 是不相关的,Selection是通过D-pad or trackball 来操作的,Click通常是点击操作的。

 我犯得错是自己在getView里面不小心设置了对Click的监听导致的。已经被我注释掉了

//    private class ClickListner implements OnClickListener {
//        private int position;
//
//        private ClickListner(int position) {
//            this.position = position;
//        }
//
//        @Override
//        public void onClick(View v) {
//        	Log.d(TAG,"xxxxxxxxxxx");
//            MCloth cloth = mCloths.get(position);
//            if (!isEnabled(position)) {
//                return;
//            }
//            Context context = v.getContext();
//            //DetailActivity.launch(context, movie, Referer.NEW_ARRIVIAL);
//        }
//    }
接下来我讲一下,如何实现PullToRefresh来实现长按进入删除选中模式。

长按进入删除模式

首先,在需要初始化View各种监听的地方,我们开一个函数。如下,相信大家都熟悉,

	private void setupViews(View rootView) {
		mListView = (PullToRefreshListView) rootView
				.findViewById(R.id.cloths_lv);
		mListView.setMode(PullToRefreshBase.Mode.BOTH);
		((ViewGroup) mListView.getParent()).addView(mErrorView);
		mListView.setEmptyView(mErrorView);
		mClothManageAdapter = new ClothManageAdapter(getActivity(),
				getImageFetcher());
		mListView.setAdapter(mClothManageAdapter);
		((MainActivity) getActivity()).getIndicator().setOnTabSelectedListener(
				mTabSelectdListener);
		mProgressBar = (ProgressBar) rootView.findViewById(R.id.pb_progress);

		setListViewRefresh();
		setLongClickListener();
	}

我们把注意力放到setLongClickListener上,这个是我封的一个private方法,如下:

	private void setLongClickListener() {
		Log.d(TAG, "setLongClick");
		mListView.getRefreshableView().setOnItemClickListener(
				mOnItemClickListener);//单击事件的监听
		mListView.getRefreshableView().setChoiceMode(
				ListView.CHOICE_MODE_MULTIPLE_MODAL);//选择模式选为可多选
		mListView.getRefreshableView().setMultiChoiceModeListener(
				mMutilChoiceListener);//多选监听

	}
好,我们再进一步看单击时间的监听

	private final OnItemClickListener mOnItemClickListener = new OnItemClickListener() {

		@Override
		public void onItemClick(AdapterView<?> parent, View view, int position,
				long id) {
			if (mActionMode == null) {//还没有按长按的时候,走这里。
				Log.d(TAG, "onItemClick,mActionMode is null");
			} else {//已经有了一次长按之后,进入了选择模式,走这里
				Log.d(TAG, "onItemClick,mActionMode is  not null, select item "
						+ position + " to select");
				mListView.getRefreshableView().setItemChecked(position, true);

			}
		}
	};
好,我们看我们很关键的多选监听。直接上代码

	private final MultiChoiceModeListener mMutilChoiceListener = new MultiChoiceModeListener() {
		@Override
		public boolean onCreateActionMode(ActionMode mode, Menu menu) {
			Log.d(TAG, "onCreateActionMode, mode:" + mode + ",menu:" + menu);
			mActionMode = mode;
			getActivity().getMenuInflater().inflate(
					R.menu.menu_favorite_delete, menu);//加载菜单到ActionBar中

			return true;
		}

		@Override
		public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
			return false;
		}

		@Override
		public void onDestroyActionMode(ActionMode mode) {
			mActionMode = null;
		}

		@Override
		public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
			switch (item.getItemId()) {//菜单点击事件
			case R.id.menu_delete: // 删除
				Log.d(TAG,"delete menu");
				List<MCloth> deleted = new ArrayList<MCloth>();
				SparseBooleanArray checked = mListView.getRefreshableView()
						.getCheckedItemPositions();
				for (int i = 0; i < checked.size(); i++) {
					Log.d(TAG, "get from Adapter("+checked.keyAt(i)+","+checked.valueAt(i)+")");
					if (checked.valueAt(i)) {
						deleted.add(mClothManageAdapter.getItem(checked
								.keyAt(i)));
					}
				}
//				for (MCloth cloth : deleted) {
//					if(cloth != null){
//						//Log.d(TAG, "deleting the cloth id="+cloth.id+" in remote server now");
//						 WEBInterface1.DelCloth(cloth.id);
//					}
//				}
				new DeleteClothTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, deleted);
				mClothManageAdapter.remove(deleted);

				mode.finish();
				loadData(true);
				break;
			case R.id.menu_selectall: // 全选
				if (mIsSelectAll) {
					item.setTitle("取消全选");
					mIsSelectAll = false;

				} else {
					item.setTitle("全选");
					mIsSelectAll = true;
				}
				for (int i = 0; i < mListView.getRefreshableView().getCount(); i++) {
					mListView.getRefreshableView().setItemChecked(i,
							!mIsSelectAll);
				}
				break;
			}
			return true;
		}

		@Override
		public void onItemCheckedStateChanged(ActionMode mode, int position,
				long id, boolean checked) {
			setActionModeTitle(mode, mListView.getRefreshableView()
					.getCheckedItemCount());
		}

	};

	private void setActionModeTitle(ActionMode mode, int count) {
		Log.d(TAG, "setActionModeTitile,mode:" + mode + ",count:" + count);
		mActionMode.setTitle("选中" + count + "个布料");
	}
这样
核心的代码就是上面了,实现了长按删除的,效果不错吧。不懂的可以联系我。希望我们的搜芽产品能够一天天的长成大树。 晚安。有想加入我们团队的,也可以联系我。我会给你力所能及的帮助,也期待大家的愉快合作。










相关文章
|
18天前
|
开发框架 前端开发 Android开发
安卓与iOS开发中的跨平台策略
在移动应用开发的战场上,安卓和iOS两大阵营各据一方。随着技术的演进,跨平台开发框架成为开发者的新宠,旨在实现一次编码、多平台部署的梦想。本文将探讨跨平台开发的优势与挑战,并分享实用的开发技巧,帮助开发者在安卓和iOS的世界中游刃有余。
|
24天前
|
搜索推荐 Android开发 开发者
探索安卓开发中的自定义视图:打造个性化UI组件
【10月更文挑战第39天】在安卓开发的世界中,自定义视图是实现独特界面设计的关键。本文将引导你理解自定义视图的概念、创建流程,以及如何通过它们增强应用的用户体验。我们将从基础出发,逐步深入,最终让你能够自信地设计和实现专属的UI组件。
|
6天前
|
搜索推荐 前端开发 API
探索安卓开发中的自定义视图:打造个性化用户界面
在安卓应用开发的广阔天地中,自定义视图是一块神奇的画布,让开发者能够突破标准控件的限制,绘制出独一无二的用户界面。本文将带你走进自定义视图的世界,从基础概念到实战技巧,逐步揭示如何在安卓平台上创建和运用自定义视图来提升用户体验。无论你是初学者还是有一定经验的开发者,这篇文章都将为你打开新的视野,让你的应用在众多同质化产品中脱颖而出。
33 19
|
10天前
|
Java 调度 Android开发
安卓与iOS开发中的线程管理差异解析
在移动应用开发的广阔天地中,安卓和iOS两大平台各自拥有独特的魅力。如同东西方文化的差异,它们在处理多线程任务时也展现出不同的哲学。本文将带你穿梭于这两个平台之间,比较它们在线程管理上的核心理念、实现方式及性能考量,助你成为跨平台的编程高手。
|
26天前
|
Android开发 Swift iOS开发
探索安卓与iOS开发的差异和挑战
【10月更文挑战第37天】在移动应用开发的广阔舞台上,安卓和iOS这两大操作系统扮演着主角。它们各自拥有独特的特性、优势以及面临的开发挑战。本文将深入探讨这两个平台在开发过程中的主要差异,从编程语言到用户界面设计,再到市场分布的不同影响,旨在为开发者提供一个全面的视角,帮助他们更好地理解并应对在不同平台上进行应用开发时可能遇到的难题和机遇。
|
26天前
|
存储 API 开发工具
探索安卓开发:从基础到进阶
【10月更文挑战第37天】在这篇文章中,我们将一起探索安卓开发的奥秘。无论你是初学者还是有经验的开发者,这篇文章都将为你提供有价值的信息和建议。我们将从安卓开发的基础开始,逐步深入到更复杂的主题,如自定义组件、性能优化等。最后,我们将通过一个代码示例来展示如何实现一个简单的安卓应用。让我们一起开始吧!
|
6天前
|
Java Android开发 开发者
探索安卓开发:构建你的第一个“Hello World”应用
在安卓开发的浩瀚海洋中,每个新手都渴望扬帆起航。本文将作为你的指南针,引领你通过创建一个简单的“Hello World”应用,迈出安卓开发的第一步。我们将一起搭建开发环境、了解基本概念,并编写第一行代码。就像印度圣雄甘地所说:“你必须成为你希望在世界上看到的改变。”让我们一起开始这段旅程,成为我们想要见到的开发者吧!
13 0
|
28天前
|
XML 存储 Java
探索安卓开发之旅:从新手到专家
【10月更文挑战第35天】在数字化时代,安卓应用的开发成为了一个热门话题。本文旨在通过浅显易懂的语言,带领初学者了解安卓开发的基础知识,同时为有一定经验的开发者提供进阶技巧。我们将一起探讨如何从零开始构建第一个安卓应用,并逐步深入到性能优化和高级功能的实现。无论你是编程新手还是希望提升技能的开发者,这篇文章都将为你提供有价值的指导和灵感。
|
26天前
|
存储 XML JSON
探索安卓开发:从新手到专家的旅程
【10月更文挑战第36天】在这篇文章中,我们将一起踏上一段激动人心的旅程,从零基础开始,逐步深入安卓开发的奥秘。无论你是编程新手,还是希望扩展技能的老手,这里都有适合你的知识宝藏等待发掘。通过实际的代码示例和深入浅出的解释,我们将解锁安卓开发的关键技能,让你能够构建自己的应用程序,甚至贡献于开源社区。准备好了吗?让我们开始吧!
26 2
|
28天前
|
Android开发
布谷语音软件开发:android端语音软件搭建开发教程
语音软件搭建android端语音软件开发教程!