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

Android 模仿QQ侧滑删除ListView功能示例

程序员文章站 2023-12-01 13:37:22
需求: 1、listview可以侧滑item,展示删除按钮,点击删除按钮,删除当前的item 2、在删除按钮展示时,点击隐藏删除按钮,不响应item的点击事件 3、在...

需求:

1、listview可以侧滑item,展示删除按钮,点击删除按钮,删除当前的item

2、在删除按钮展示时,点击隐藏删除按钮,不响应item的点击事件

3、在删除按钮隐藏时,点击item响应点击事件

根据以上需求在网络上查找响应的例子,也有仿qq侧滑代码,但不能满足2和3的要求,因此修改了一把,代码如下,共大家拍砖

第一步:重写listview

public class swipelistview extends listview {
  private final static string tag = "swipelistview";
  private int mscreenwidth;  // 屏幕宽度
  private int mdownx;      // 按下点的x值
  private int mdowny;      // 按下点的y值
  private int mdeletebtnwidth;// 删除按钮的宽度
  private boolean isdeleteshown = false;  // 删除按钮是否正在显示
  private boolean isonclick = false;
  private viewgroup mpointchild;  // 当前处理的item
  private linearlayout.layoutparams mlayoutparams;  // 当前处理的item的layoutparams
  public swipelistview(context context, attributeset attrs) {
    this(context, attrs, 0);
  }
  public swipelistview(context context, attributeset attrs, int defstyle) {
    super(context, attrs, defstyle);
    // 获取屏幕宽度
    windowmanager wm = (windowmanager) context.getsystemservice(context.window_service);
    displaymetrics dm = new displaymetrics();
    wm.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:
        return performactionmove(ev);
      case motionevent.action_up:
        return performactionup(ev);
//        break;
    }
    return super.ontouchevent(ev);
  }
  // 处理action_down事件
  private void performactiondown(motionevent ev) {
//    log.e(tag,"performactiondown===="+isdeleteshown);
    if (isdeleteshown) {
      turntonormal();
    }
    isonclick = true;
    mdownx = (int) ev.getx();
    mdowny = (int) ev.gety();
    // 获取当前点的item
    int downposition = pointtoposition(mdownx, mdowny);
    int firstposition= getfirstvisibleposition();
    log.e(tag,"performactiondown====downposition:"+downposition+"==firstposition"+firstposition);
    if(downposition < 0) return;
    mpointchild = (viewgroup) getchildat(downposition-firstposition);
    // 获取删除按钮的宽度
    mdeletebtnwidth = mpointchild.getchildat(1).getlayoutparams().width;
    mlayoutparams = (linearlayout.layoutparams) mpointchild.getchildat(0)
        .getlayoutparams();
    // 为什么要重新设置layout_width 等于屏幕宽度
    // 因为match_parent时,不管你怎么滑,都不会显示删除按钮
    // why? 因为match_parent时,viewgroup就不去布局剩下的view
    mlayoutparams.width = mscreenwidth;
    mpointchild.getchildat(0).setlayoutparams(mlayoutparams);
  }
  // 处理action_move事件
  private boolean performactionmove(motionevent ev) {
//    log.e(tag, "performactionmove====" + isdeleteshown);
    int nowx = (int) ev.getx();
    int nowy = (int) ev.gety();
    isonclick = false;
    if (math.abs(nowx - mdownx) > math.abs(nowy - mdowny)) {
      // 如果向左滑动
      if (nowx < mdownx) {
        // 计算要偏移的距离
        int scroll = (nowx - mdownx) / 2;
        // 如果大于了删除按钮的宽度, 则最大为删除按钮的宽度
        if (-scroll >= mdeletebtnwidth) {
          scroll = -mdeletebtnwidth;
        }
        // 重新设置leftmargin
        mlayoutparams.leftmargin = scroll;
        mpointchild.getchildat(0).setlayoutparams(mlayoutparams);
      }
      return true;
    }
    return super.ontouchevent(ev);
  }
  // 处理action_up事件
  private boolean performactionup(motionevent ev) {
    boolean falg = false;
    if(isonclick && !isdeleteshown)
    {
      falg = true;
    }
    // 偏移量大于button的一半,则显示button
    // 否则恢复默认
    if (-mlayoutparams.leftmargin >= mdeletebtnwidth / 2) {
      mlayoutparams.leftmargin = -mdeletebtnwidth;
      isdeleteshown = true;
    } else {
      turntonormal();
      isdeleteshown = false;
    }
    mpointchild.getchildat(0).setlayoutparams(mlayoutparams);
//    log.e(tag, "performactionup====" + isdeleteshown);
    if(falg)
    {
      return super.ontouchevent(ev);
    }
    return true;
  }
  /**
   * 变为正常状态
   */
  public void turntonormal() {
    mlayoutparams.leftmargin = 0;
    mpointchild.getchildat(0).setlayoutparams(mlayoutparams);
  }
  /**
   * 当前是否可点击
   *
   * @return 是否可点击
   */
  public boolean canclick() {
    return !isdeleteshown;
  }
}

第二步:适配器

class swipelistadapter extends baseadapter {
  @override
  public int getcount() {
    return mdata.size();
  }
  @override
  public object getitem(int position) {
    return mdata.get(position);
  }
  @override
  public long getitemid(int position) {
    return position;
  }
  @override
  public view getview(int position, view convertview, viewgroup parent) {
    viewholder holder = null;
    if (null == convertview) {
      holder = new viewholder();
      convertview = view.inflate(testlistviewactivity.this, r.layout.item_swipe_list, null);
      holder.tv = (linearlayout) convertview.findviewbyid(r.id.tv);
      holder.tvname = (textview) convertview.findviewbyid(r.id.tv_name);
      holder.delete = (textview) convertview.findviewbyid(r.id.delete);
      convertview.settag(holder);
    }
    else {
      holder = (viewholder) convertview.gettag();
    }
    holder.tvname.settext(mdata.get(position));
    final int pos = position;
    holder.delete.setonclicklistener(new view.onclicklistener() {
      @override
      public void onclick(view v) {
        mdata.remove(pos);
        notifydatasetchanged();
        mlistview.turntonormal();
      }
    });
    return convertview;
  }
}
static class viewholder {
  linearlayout tv;
  textview tvname;
  textview delete;
}

第三步:写一个testlistviewactivity

private swipelistview mlistview;
  private arraylist<string> mdata = new arraylist<string>() {
    {
      for (int i = 0; i < 20; i++) {
        add("hello world, hello android " + i);
      }
    }
  };
  @override
  protected void oncreate(bundle savedinstancestate) {
    super.oncreate(savedinstancestate);
    setcontentview(r.layout.activity_test_list_view);
    toolbar toolbar = (toolbar) findviewbyid(r.id.toolbar);
    setsupportactionbar(toolbar);
    floatingactionbutton fab = (floatingactionbutton) findviewbyid(r.id.fab);
    fab.setonclicklistener(new view.onclicklistener() {
      @override
      public void onclick(view view) {
        snackbar.make(view, "replace with your own action", snackbar.length_long)
            .setaction("action", null).show();
      }
    });
    mlistview = (swipelistview) findviewbyid(r.id.list);
    mlistview.setadapter(new swipelistadapter());
//    mlistview.setonitemlongclicklistener(new adapterview.onitemlongclicklistener() {
//      @override
//      public boolean onitemlongclick(adapterview<?> parent, view view, int position, long id) {
//        toast.maketext(testlistviewactivity.this, mdata.get(position) + "被点击了",
//            toast.length_short).show();
//        return false;
//      }
//    });
    mlistview.setonitemclicklistener(new adapterview.onitemclicklistener() {
      @override
      public void onitemclick(adapterview<?> parent, view view, int position, long id) {
        log.e("swipelistview", "setonitemclicklistener====" + mlistview.canclick());
//        toast.maketext(testlistviewactivity.this, mdata.get(position) + "被点击了",
//            toast.length_short).show();
      }
    });
  }

第四步:布局文件

<?xml version="1.0" encoding="utf-8"?>
<relativelayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent"
  android:layout_height="match_parent" 
  app:layout_behavior="@string/appbar_scrolling_view_behavior"
  tools:showin="@layout/activity_test_list_view"
  tools:context="com.kimascend.ledappd1.activity.testlistviewactivity">
  <com.kimascend.ledappd1.view.swipelistview
    android:id="@+id/list"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:cachecolorhint="@android:color/transparent"
    android:listselector="@android:color/transparent"
    android:divider="@android:color/darker_gray"
    android:dividerheight="2dp">
  </com.kimascend.ledappd1.view.swipelistview>
</relativelayout>

第五步:item的布局文件

<?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:orientation="horizontal">
  <linearlayout
    android:id="@+id/tv"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@android:color/white"
    android:paddingbottom="20dp"
    android:paddingleft="10dp"
    android:paddingtop="20dp">
    <imageview
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:background="@drawable/group_name_rgb"
      android:id="@+id/imageview8" />
    <textview
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:textappearance="?android:attr/textappearancelarge"
      android:text="large text"
      android:layout_gravity="center_vertical"
      android:id="@+id/tv_name" />
  </linearlayout>
  <textview
    android:id="@+id/delete"
    android:layout_width="80dp"
    android:layout_height="match_parent"
    android:background="#ffff0000"
    android:gravity="center"
    android:paddingleft="20dp"
    android:paddingright="20dp"
    android:text="删除"
    android:textcolor="@android:color/white" />
</linearlayout>

重点注意:

int downposition = pointtoposition(mdownx, mdowny);

downposition 在使用过程中得到-1,导致后面方法调用异常!

以上所述是小编给大家介绍的android 模仿qq侧滑删除listview功能示例,希望对大家有所帮助