Android实现滑动删除操作(PopupWindow)
参考android仿腾讯qq实现滑动删除这篇文章进行学习,文章实现的功能是:在listview的item上从右向左滑时,出现删除按钮,点击删除按钮把item删除,效果
看过文章后,感觉没有必要把dispatchtouchevent()和ontouchevent()两个方法都重写,只要重写ontouchevent就好了。于是对代码作了一些调整:
public class mylistview extends listview { private static final string tag = "mylistview"; private int mtouchslop; private int mxdown; private int mydown; private int mcurrentposition; private view mcurrentview; private popupwindow mpopupwindow; private layoutinflater minflater; private boolean issliding = false; // 为删除按钮提供一个回调接口 private delbuttonclicklistener mlistener; private button mdelbtn; private int mpopupwindowheight; private int mpopupwindowwidth; public mylistview(context context, attributeset attrs) { super(context, attrs); minflater = layoutinflater.from(context); mtouchslop = viewconfiguration.get(context).getscaledtouchslop(); view view = minflater.inflate(r.layout.delete_btn, null); mdelbtn = (button) view.findviewbyid(r.id.id_item_btn); mpopupwindow = new popupwindow(view, linearlayout.layoutparams.wrap_content, linearlayout.layoutparams.wrap_content); // 如果需要通过点击popupwindow之外的地方使其消失,则需要setfocusable(true). mpopupwindow.setfocusable(true); // android 6.0以前的版本需要setbackgrounddrawable(), // 才能实现通过点击popupwindow之外的地方使其消失的功能。 mpopupwindow.setbackgrounddrawable(new colordrawable(0)); // 先调用下measure,否则拿不到宽和高 mpopupwindow.getcontentview().measure(0, 0); mpopupwindowheight = mpopupwindow.getcontentview().getmeasuredheight(); mpopupwindowwidth = mpopupwindow.getcontentview().getmeasuredwidth(); } @override public boolean ontouchevent(motionevent ev) { int action = ev.getaction(); int x = (int) ev.getx(); int y = (int) ev.gety(); switch (action){ case motionevent.action_down: issliding = false; mxdown = x; mydown = y; mcurrentposition = pointtoposition(mxdown, mydown); view view = getchildat(mcurrentposition - getfirstvisibleposition()); mcurrentview = view; break; case motionevent.action_move: int dx = x - mxdown; int dy = 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 = new int[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(new onclicklistener() { @override public void onclick(view v) { mlistener.clickhappend(mcurrentposition); mpopupwindow.dismiss(); } }); } case motionevent.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){ return true; } return super.ontouchevent(ev); } public void setdelbuttonclicklistener(delbuttonclicklistener listener){ mlistener = listener; } interface delbuttonclicklistener{ public void clickhappend(int position); } }
通过这个例子学习到:
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直接return true消费掉事件,而不要调用super.ontouchevent。这样就避免了删除按钮与item点击事件的冲突。
2、popupwindow--通过点击popupwindow之外的地方使其消失
a、需要调用setfocusable()方法(popupwindow中showatlocation() --> createpopuplayoutparams() --> computeflags() --> 设置flag_not_focusable);
b、android 6.0以前的版本需要setbackgrounddrawable()(具体原因见:popupwindow的使用)。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: java实现变更文件查询的方法
下一篇: java实现日期拆分的方法