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

Android仿QQ左滑删除置顶ListView操作

程序员文章站 2024-02-28 09:47:10
最近闲来无事,于是研究了一下qq的左滑删除效果,尝试着实现了一下,先上效果图: 大致思路原理: - 通过设置margin实现菜单的显示与隐藏 - 监听onto...

最近闲来无事,于是研究了一下qq的左滑删除效果,尝试着实现了一下,先上效果图:

Android仿QQ左滑删除置顶ListView操作

大致思路原理:
- 通过设置margin实现菜单的显示与隐藏
- 监听ontouchevent,处理滑动事件

上代码

import android.content.context;
import android.util.attributeset;
import android.util.displaymetrics;
import android.view.motionevent;
import android.view.viewgroup;
import android.view.windowmanager;
import android.widget.linearlayout;
import android.widget.listview;

/**
 * created by mooreli on 2016/8/8.
 */
public class slidelistview extends listview {
  private string tag = getclass().getsimplename();

  private int mscreenwidth;
  private int mdownx;
  private int mdowny;
  private int mmenuwidth;

  private boolean ismenushow;
  private boolean ismoving;

  private int moperateposition = -1;
  private viewgroup mpointchild;
  private linearlayout.layoutparams mlayoutparams;

  public slidelistview(context context) {
    super(context);
    getscreenwidth(context);
  }

  public slidelistview(context context, attributeset attrs) {
    super(context, attrs);
    getscreenwidth(context);
  }

  public slidelistview(context context, attributeset attrs, int defstyleattr) {
    super(context, attrs, defstyleattr);
    getscreenwidth(context);
  }

  private void getscreenwidth(context context) {
    windowmanager manager = (windowmanager) context.getsystemservice(context.window_service);
    displaymetrics dm = new displaymetrics();
    manager.getdefaultdisplay().getmetrics(dm);
    mscreenwidth = dm.widthpixels;
  }

  @override
  public boolean ontouchevent(motionevent ev) {
    switch (ev.getaction()) {
      case motionevent.action_down:
        performactiondown(ev);
        break;
      case motionevent.action_move:
        performactionmove(ev);
        break;
      case motionevent.action_up:
        performactionup();
        break;
    }
    return super.ontouchevent(ev);
  }

  private void performactiondown(motionevent ev) {
    mdownx = (int) ev.getx();
    mdowny = (int) ev.gety();
    //如果点击的不是同一个item,则关掉正在显示的菜单
    int position = pointtoposition(mdownx, mdowny);
    if (ismenushow && position != moperateposition) {
      turntonormal();
    }
    moperateposition = position;
    mpointchild = (viewgroup) getchildat(position - getfirstvisibleposition());
    if (mpointchild != null) {
      mmenuwidth = mpointchild.getchildat(1).getlayoutparams().width;
      mlayoutparams = (linearlayout.layoutparams) mpointchild.getchildat(0).getlayoutparams();
      mlayoutparams.width = mscreenwidth;
      setchildlayoutparams();
    }
  }

  private boolean performactionmove(motionevent ev) {
    int nowx = (int) ev.getx();
    int nowy = (int) ev.gety();
//    if (ismoving) {
//      if (math.abs(nowy - mdowny) > 0) {
//        log.e(tag, "kkkkkkk");
//        onintercepttouchevent(ev);
//      }
//    }
    if (math.abs(nowx - mdownx) > 0) {
      //左滑 显示菜单
      if (nowx < mdownx) {
        if (ismenushow) {
          mlayoutparams.leftmargin = -mmenuwidth;
        } else {
          //计算显示的宽度
          int scroll = (nowx - mdownx);
          if (-scroll >= mmenuwidth) {
            scroll = -mmenuwidth;
          }
          mlayoutparams.leftmargin = scroll;
        }
      }
      //右滑 如果菜单显示状态,则关闭菜单
      if (ismenushow && nowx > mdownx) {
        int scroll = nowx - mdownx;
        if (scroll >= mmenuwidth) {
          scroll = mmenuwidth;
        }
        mlayoutparams.leftmargin = scroll - mmenuwidth;
      }
      setchildlayoutparams();
      ismoving = true;
      return true;
    }

    return super.ontouchevent(ev);
  }

  private void performactionup() {
    //超过一半时,显示菜单,否则隐藏
    if (-mlayoutparams.leftmargin >= mmenuwidth / 2) {
      mlayoutparams.leftmargin = -mmenuwidth;
      setchildlayoutparams();
      ismenushow = true;
    } else {
      turntonormal();
    }
    ismoving = false;
  }

  private void setchildlayoutparams(){
    if(mpointchild != null){
      mpointchild.getchildat(0).setlayoutparams(mlayoutparams);
    }
  }

  /**
   * 正常显示
   */
  public void turntonormal() {
    mlayoutparams.leftmargin = 0;
    moperateposition = -1;
    setchildlayoutparams();
    ismenushow = false;
  }
}

item的布局要注意,因为在自定义view中写死的是获取第一个子布局为显示内容,所以需要将显示的样式写在一个容器中,将菜单写在另一个容器中,两个平行的关系。
xml文件定义如下:

<?xml version="1.0" encoding="utf-8"?>
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:background="#ffffff"
  android:orientation="horizontal">

  <linearlayout
    android:layout_width="match_parent"
    android:layout_height="60dp"
    android:orientation="horizontal">

    <textview
      android:id="@+id/main_tv_title"
      android:layout_width="wrap_content"
      android:layout_height="match_parent"
      android:layout_marginleft="10dp"
      android:gravity="center_vertical"
      android:textsize="18sp" />
  </linearlayout>

  <linearlayout
    android:layout_width="180dp"
    android:layout_height="60dp"
    android:orientation="horizontal">

    <textview
      android:id="@+id/main_tv_delete"
      android:layout_width="0dp"
      android:layout_height="match_parent"
      android:layout_weight="1"
      android:background="#ff0000"
      android:gravity="center"
      android:text="删除"
      android:textcolor="#ffffff" />

    <textview
      android:id="@+id/main_tv_top"
      android:layout_width="0dp"
      android:layout_height="match_parent"
      android:layout_weight="1"
      android:background="#dfcdbf"
      android:gravity="center"
      android:text="置顶"
      android:textcolor="#ffffff" />
  </linearlayout>
</linearlayout>

最后就是删除操作与置顶操作,这个就比较简单,给按钮添加点击事件即可。我是在adapter中定义实现,记得操作后要将菜单关掉!

上部分代码: 

    holder.tvtitle.settext(minfos.get(position));
    holder.tvdelete.setonclicklistener(new view.onclicklistener() {
      @override
      public void onclick(view v) {
        minfos.remove(position);
        notifydatasetchanged();
        mlistview.turntonormal();
      }
    });
    holder.tvtop.setonclicklistener(new view.onclicklistener() {
      @override
      public void onclick(view v) {
        string temp = minfos.get(position);
        minfos.remove(position);
        minfos.add(0, temp);
        notifydatasetchanged();
        mlistview.turntonormal();
      }
    });

最后还有一个遗留问题,listview左右滑动的时候上下也会滑动,这个有待探索与改进,也希望大家提提意见,帮我改进!

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