zoukankan      html  css  js  c++  java
  • Android开发之PullToRefresh的Click点击事件的监听实现长按删除Item

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

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

    项目过程进度





    从任务分配量上来看,基本还是我个人英雄主义。

    接下来这样不行。但临时也没办法。师弟还须要一个学习的过程。智质不错。并且态度端正。相信搜芽买家,他就能够承担很多其它的开发任务了。


    接下来进入正题。说我们的PullToRefresh的点击事件。

    事实上,我是想做长按进入删除的。

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

    效果图

    先上效果图



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


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


    我们还能够点击ActionBar全选来选择全部Item


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

    选中了。然后按删除菜单。就是那个垃圾桶图标就可以。

    就会删除。删除同步至server。

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

    。!

    问题排查

    网上非常多方法。

    第一个比較实用的是: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 + "个布料");
    	}
    这样
    核心的代码就是上面了。实现了长按删除的,效果不错吧。

    不懂的能够联系我。

    希望我们的搜芽产品能够一天天的长成大树。晚安。

    有想增加我们团队的,也能够联系我。

    我会给你力所能及的帮助,也期待大家的愉快合作。










  • 相关阅读:
    wince串口打印信息的屏蔽与打开
    2440 6.0BSP 移植过程之OAL
    2440 6.0BSP移植过程之电池驱动
    2440 6.0BSP移植过程之SD卡驱动
    如何在wince6.0 模拟器上跑以前编译好的EVC MFC程序
    2440 休眠唤醒的实现过程(作者:wogoyixikexie@gliet)
    CETK的使用(USB连接方式)
    如何扩展ARM内存(OEMGetExtensionDRAM和pNKEnumExtensionDRAM函数可以解决问题)
    ZLG7290(wince下)驱动之不停执行同一动作的解决办法(作者:wogoyixikexie@gliet)
    2440 中断优先级问题(作者wogoyixikexie@gliet)
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/5222879.html
Copyright © 2011-2022 走看看