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实现滑动删除功能,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对毛票票网站的支持!