当前位置: 移动技术网 > IT编程>移动开发>Android > Android仿微信对话列表滑动删除效果

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

2019年07月24日  | 移动技术网IT编程  | 我要评论

结婚仪式流程,孽子风情,宝宝腹泻能打疫苗吗

微信对话列表滑动删除效果很不错的,借鉴了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即可。

运行效果如下

下面是最核心的部分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下载地址:

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

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

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

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

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网