欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android实现滑动删除操作(PopupWindow)

程序员文章站 2024-03-05 17:27:31
参考android仿腾讯qq实现滑动删除这篇文章进行学习,文章实现的功能是:在listview的item上从右向左滑时,出现删除按钮,点击删除按钮把item删除,效果...

参考android仿腾讯qq实现滑动删除这篇文章进行学习,文章实现的功能是:在listview的item上从右向左滑时,出现删除按钮,点击删除按钮把item删除,效果

Android实现滑动删除操作(PopupWindow)

看过文章后,感觉没有必要把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的使用)。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。