Android程序开发之ListView 与PopupWindow实现从左向右滑动删除功能
文章实现的功能是:在ListView的Item上从右向左滑时,出现删除按钮,点击删除按钮把Item删除。
看过文章后,感觉没有必要把dispatchTouchEvent()和onTouchEvent()两个方法都重写,只要重写onTouchEvent就好了。于是对代码作了一些调整:
publicclassMyListViewextendsListView{ privatestaticfinalStringTAG="MyListView"; privateintmTouchSlop; privateintmXDown; privateintmYDown; privateintmCurrentPosition; privateViewmCurrentView; privatePopupWindowmPopupWindow; privateLayoutInflatermInflater; privatebooleanisSliding=false; //为删除按钮提供一个回调接口 privateDelButtonClickListenermListener; privateButtonmDelBtn; privateintmPopupWindowHeight; privateintmPopupWindowWidth; publicMyListView(Contextcontext,AttributeSetattrs){ super(context,attrs); mInflater=LayoutInflater.from(context); mTouchSlop=ViewConfiguration.get(context).getScaledTouchSlop(); Viewview=mInflater.inflate(R.layout.delete_btn,null); mDelBtn=(Button)view.findViewById(R.id.id_item_btn); mPopupWindow=newPopupWindow(view,LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT); //如果需要通过点击PopupWindow之外的地方使其消失,则需要setFocusable(true). mPopupWindow.setFocusable(true); //Android6.0以前的版本需要setBackgroundDrawable(), //才能实现通过点击PopupWindow之外的地方使其消失的功能。 mPopupWindow.setBackgroundDrawable(newColorDrawable(0)); //先调用下measure,否则拿不到宽和高 mPopupWindow.getContentView().measure(0,0); mPopupWindowHeight=mPopupWindow.getContentView().getMeasuredHeight(); mPopupWindowWidth=mPopupWindow.getContentView().getMeasuredWidth(); } @Override publicbooleanonTouchEvent(MotionEventev){ intaction=ev.getAction(); intx=(int)ev.getX(); inty=(int)ev.getY(); switch(action){ caseMotionEvent.ACTION_DOWN: isSliding=false; mXDown=x; mYDown=y; mCurrentPosition=pointToPosition(mXDown,mYDown); Viewview=getChildAt(mCurrentPosition-getFirstVisiblePosition()); mCurrentView=view; break; caseMotionEvent.ACTION_MOVE: intdx=x-mXDown; intdy=y-mYDown; Log.d(TAG,"mTouchSlop="+mTouchSlop+",dx="+dx+",dy="+dy); if(mXDown>x&&Math.abs(dx)>mTouchSlop&&Math.abs(dy)<mTouchSlop){ Log.d(TAG,"isSliding"); isSliding=true; int[]location=newint[2]; mCurrentView.getLocationOnScreen(location); mPopupWindow.setAnimationStyle(R.style.popwindow_delete_btn_anim_style); mPopupWindow.update(); Log.d(TAG,"Height:"+mCurrentView.getHeight()+","+mPopupWindow.getHeight()); mPopupWindow.showAtLocation(mCurrentView,Gravity.NO_GRAVITY, location[0]+mCurrentView.getWidth(), location[1]+mCurrentView.getHeight()/2-mPopupWindowHeight/2); mDelBtn.setOnClickListener(newOnClickListener(){ @Override publicvoidonClick(Viewv){ mListener.clickHappend(mCurrentPosition); mPopupWindow.dismiss(); } }); } caseMotionEvent.ACTION_UP: //isSliding如果这里恢复为false,则后面会执行super.onTouchEvent事件, //而AbsListView的onTouchEvent调用了onTouchUp方法,在onTouchUp方法中有可能执行 //performClick.run()-->performItemClick()-->super.performItemClick //-->mOnItemClickListener.onItemClick,这样最终触发Item的点击。 //因此此处依旧保持isSliding为true的状态,而在ACTION_DOWN事件中恢复isSliding为false, //毕竟每个事件都以ACTION_DOWN开始。 //isSliding=false; } if(isSliding){ returntrue; } returnsuper.onTouchEvent(ev); } publicvoidsetDelButtonClickListener(DelButtonClickListenerlistener){ mListener=listener; } interfaceDelButtonClickListener{ publicvoidclickHappend(intposition); } }
通过这个例子学习到:
1、ListView的Item点击事件的触发过程:
自定义ListView的onTouchEvent()---调用super.onTouchEvent()--->AbsListView.onTouchEvent()---MotionEvent.ACTION_UP--->AbsListView.onTouchUp()
---(有可能)调用performClick.run()--->AbsListView.PerformClick.run()---调用performItemClick()--->AbsListView.performItemClick()
---(有可能)调用super.performItemClick()--->AdapterView.performItemClick()---mOnItemClickListener.onItemClick--->OnItemClickListener.onItemClick()
也就是Item的点击事件是在MotionEvent.ACTION_UP事件完成的,这样在自定义ListView的onTouchEvent()中,对MotionEvent.ACTION_UP直接returntrue消费掉事件,而不要调用super.onTouchEvent。这样就避免了删除按钮与Item点击事件的冲突。
2、PopupWindow--通过点击PopupWindow之外的地方使其消失
a、需要调用setFocusable()方法;
b、Android6.0以前的版本需要setBackgroundDrawable()(具体原因见:PopupWindow的使用)。
以上所述是小编给大家介绍的Android程序开发之ListView与PopupWindow实现滑动删除功能,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对毛票票网站的支持!