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

Android仿微信对话列表滑动删除效果

程序员文章站 2024-03-06 17:43:14
微信对话列表滑动删除效果很不错的,借鉴了github上swipelistview(项目地址:https://github.com/likebamboo/swipelistv...

微信对话列表滑动删除效果很不错的,借鉴了github上swipelistview(项目地址:https://github.com/likebamboo/swipelistview),在其上进行了一些重构,最终实现了微信对话列表滑动删除效果。

实现原理
 1.通过listview的pointtoposition(int x, int y)来获取按下的position,然后通过android.view.viewgroup.getchildat(position)来得到滑动对象swipeview
 2.在ontouchevent中计算要滑动的距离,调用swipeview.scrollto即可。

运行效果如下

Android仿微信对话列表滑动删除效果

Android仿微信对话列表滑动删除效果

Android仿微信对话列表滑动删除效果

下面是最核心的部分swipelistview代码: 

package com.fxsky.swipelist.widget;

import android.annotation.suppresslint;
import android.content.context;
import android.content.res.typedarray;
import android.os.handler;
import android.os.message;
import android.util.attributeset;
import android.view.motionevent;
import android.view.view;
import android.widget.listview;

import com.fxsky.swipelist.r;

public class swipelistview extends listview {
 private boolean mishorizontal;

 private view mpreitemview;

 private view mcurrentitemview;

 private float mfirstx;

 private float mfirsty;

 private int mrightviewwidth;

 // private boolean misinanimation = false;
 private final int mduration = 100;

 private final int mdurationstep = 10;

 private boolean misshown;

 public swipelistview(context context) {
 this(context,null);
 }

 public swipelistview(context context, attributeset attrs) {
 this(context, attrs,0);
 }

 public swipelistview(context context, attributeset attrs, int defstyle) {
 super(context, attrs, defstyle);
 
 typedarray mtypedarray = context.obtainstyledattributes(attrs, 
 r.styleable.swipelistviewstyle); 
 
 //获取自定义属性和默认值 
 mrightviewwidth = (int) mtypedarray.getdimension(r.styleable.swipelistviewstyle_right_width, 200); 
 
 mtypedarray.recycle(); 
 }

 /**
 * return true, deliver to listview. return false, deliver to child. if
 * move, return true
 */
 @override
 public boolean onintercepttouchevent(motionevent ev) {
 float lastx = ev.getx();
 float lasty = ev.gety();
 switch (ev.getaction()) {
 case motionevent.action_down:
 mishorizontal = null;
 system.out.println("onintercepttouchevent----->action_down");
 mfirstx = lastx;
 mfirsty = lasty;
 int motionposition = pointtoposition((int)mfirstx, (int)mfirsty);

 if (motionposition >= 0) {
  view currentitemview = getchildat(motionposition - getfirstvisibleposition());
  mpreitemview = mcurrentitemview;
  mcurrentitemview = currentitemview;
 }
 break;

 case motionevent.action_move:
 float dx = lastx - mfirstx;
 float dy = lasty - mfirsty;

 if (math.abs(dx) >= 5 && math.abs(dy) >= 5) {
  return true;
 }
 break;

 case motionevent.action_up:
 case motionevent.action_cancel:
 system.out.println("onintercepttouchevent----->action_up");
 if (misshown && (mpreitemview != mcurrentitemview || ishitcuritemleft(lastx))) {
  system.out.println("1---> hiddenright");
  /**
  * 情况一:
  * <p>
  * 一个item的右边布局已经显示,
  * <p>
  * 这时候点击任意一个item, 那么那个右边布局显示的item隐藏其右边布局
  */
  hiddenright(mpreitemview);
 }
 break;
 }

 return super.onintercepttouchevent(ev);
 }

 private boolean ishitcuritemleft(float x) {
 return x < getwidth() - mrightviewwidth;
 }

 /**
 * @param dx
 * @param dy
 * @return judge if can judge scroll direction
 */
 private boolean judgescrolldirection(float dx, float dy) {
 boolean canjudge = true;

 if (math.abs(dx) > 30 && math.abs(dx) > 2 * math.abs(dy)) {
 mishorizontal = true;
 system.out.println("mishorizontal---->" + mishorizontal);
 } else if (math.abs(dy) > 30 && math.abs(dy) > 2 * math.abs(dx)) {
 mishorizontal = false;
 system.out.println("mishorizontal---->" + mishorizontal);
 } else {
 canjudge = false;
 }

 return canjudge;
 }

 /**
 * return false, can't move any direction. return true, cant't move
 * vertical, can move horizontal. return super.ontouchevent(ev), can move
 * both.
 */
 @override
 public boolean ontouchevent(motionevent ev) {
 float lastx = ev.getx();
 float lasty = ev.gety();

 switch (ev.getaction()) {
 case motionevent.action_down:
 system.out.println("---->action_down");
 break;

 case motionevent.action_move:
 float dx = lastx - mfirstx;
 float dy = lasty - mfirsty;

 // confirm is scroll direction
 if (mishorizontal == null) {
  if (!judgescrolldirection(dx, dy)) {
  break;
  }
 }

 if (mishorizontal) {
  if (misshown && mpreitemview != mcurrentitemview) {
  system.out.println("2---> hiddenright");
  /**
  * 情况二:
  * <p>
  * 一个item的右边布局已经显示,
  * <p>
  * 这时候左右滑动另外一个item,那个右边布局显示的item隐藏其右边布局
  * <p>
  * 向左滑动只触发该情况,向右滑动还会触发情况五
  */
  hiddenright(mpreitemview);
  }

  if (misshown && mpreitemview == mcurrentitemview) {
  dx = dx - mrightviewwidth;
  system.out.println("======dx " + dx);
  }

  // can't move beyond boundary
  if (dx < 0 && dx > -mrightviewwidth) {
  mcurrentitemview.scrollto((int)(-dx), 0);
  }

  return true;
 } else {
  if (misshown) {
  system.out.println("3---> hiddenright");
  /**
  * 情况三:
  * <p>
  * 一个item的右边布局已经显示,
  * <p>
  * 这时候上下滚动listview,那么那个右边布局显示的item隐藏其右边布局
  */
  hiddenright(mpreitemview);
  }
 }

 break;

 case motionevent.action_up:
 case motionevent.action_cancel:
 system.out.println("============action_up");
 clearpressedstate();
 if (misshown) {
  system.out.println("4---> hiddenright");
  /**
  * 情况四:
  * <p>
  * 一个item的右边布局已经显示,
  * <p>
  * 这时候左右滑动当前一个item,那个右边布局显示的item隐藏其右边布局
  */
  hiddenright(mpreitemview);
 }

 if (mishorizontal != null && mishorizontal) {
  if (mfirstx - lastx > mrightviewwidth / 2) {
  showright(mcurrentitemview);
  } else {
  system.out.println("5---> hiddenright");
  /**
  * 情况五:
  * <p>
  * 向右滑动一个item,且滑动的距离超过了右边view的宽度的一半,隐藏之。
  */
  hiddenright(mcurrentitemview);
  }

  return true;
 }

 break;
 }

 return super.ontouchevent(ev);
 }

 private void clearpressedstate() {
 // todo current item is still has background, issue
 mcurrentitemview.setpressed(false);
 setpressed(false);
 refreshdrawablestate();
 // invalidate();
 }

 private void showright(view view) {
 system.out.println("=========showright");

 message msg = new movehandler().obtainmessage();
 msg.obj = view;
 msg.arg1 = view.getscrollx();
 msg.arg2 = mrightviewwidth;
 msg.sendtotarget();

 misshown = true;
 }

 private void hiddenright(view view) {
 system.out.println("=========hiddenright");
 if (mcurrentitemview == null) {
 return;
 }
 message msg = new movehandler().obtainmessage();//
 msg.obj = view;
 msg.arg1 = view.getscrollx();
 msg.arg2 = 0;

 msg.sendtotarget();

 misshown = false;
 }

 /**
 * show or hide right layout animation
 */
 @suppresslint("handlerleak")
 class movehandler extends handler {
 int stepx = 0;

 int fromx;

 int tox;

 view view;

 private boolean misinanimation = false;

 private void animatioover() {
 misinanimation = false;
 stepx = 0;
 }

 @override
 public void handlemessage(message msg) {
 super.handlemessage(msg);
 if (stepx == 0) {
 if (misinanimation) {
  return;
 }
 misinanimation = true;
 view = (view)msg.obj;
 fromx = msg.arg1;
 tox = msg.arg2;
 stepx = (int)((tox - fromx) * mdurationstep * 1.0 / mduration);
 if (stepx < 0 && stepx > -1) {
  stepx = -1;
 } else if (stepx > 0 && stepx < 1) {
  stepx = 1;
 }
 if (math.abs(tox - fromx) < 10) {
  view.scrollto(tox, 0);
  animatioover();
  return;
 }
 }

 fromx += stepx;
 boolean islaststep = (stepx > 0 && fromx > tox) || (stepx < 0 && fromx < tox);
 if (islaststep) {
 fromx = tox;
 }

 view.scrollto(fromx, 0);
 invalidate();

 if (!islaststep) {
 this.sendemptymessagedelayed(0, mdurationstep);
 } else {
 animatioover();
 }
 }
 }

 public int getrightviewwidth() {
 return mrightviewwidth;
 }

 public void setrightviewwidth(int mrightviewwidth) {
 this.mrightviewwidth = mrightviewwidth;
 }
}

demo下载地址:http://xiazai.jb51.net/201608/yuanma/swipelistview(jb51.net).rar

demo中swipeadapter源码中有一处由于粗心写错了,会导致向下滑动时出现数组越界异常,现更正如下:

@override
 public int getcount() {
// return 100;
 return data.size();
 }

本文已被整理到了《android微信开发教程汇总》,欢迎大家学习阅读。

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