android中聊天脏字过滤,Android仿微信对话列表滑动删除效果

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

运行效果如下

156a64671374307a5fbcd3e266100c69.png

97cd8f6632dc8637e0af3aa6793abdb5.png

7bb206e8e3509117619dc0f6b91d0a74.png

下面是最核心的部分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");

/**

* 情况一:

*

* 一个Item的右边布局已经显示,

*

* 这时候点击任意一个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");

/**

* 情况二:

*

* 一个Item的右边布局已经显示,

*

* 这时候左右滑动另外一个item,那个右边布局显示的item隐藏其右边布局

*

* 向左滑动只触发该情况,向右滑动还会触发情况五

*/

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");

/**

* 情况三:

*

* 一个Item的右边布局已经显示,

*

* 这时候上下滚动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");

/**

* 情况四:

*

* 一个Item的右边布局已经显示,

*

* 这时候左右滑动当前一个item,那个右边布局显示的item隐藏其右边布局

*/

hiddenRight(mPreItemView);

}

if (mIsHorizontal != null && mIsHorizontal) {

if (mFirstX - lastX > mRightViewWidth / 2) {

showRight(mCurrentItemView);

} else {

System.out.println("5---> hiddenRight");

/**

* 情况五:

*

* 向右滑动一个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中SwipeAdapter源码中有一处由于粗心写错了,会导致向下滑动时出现数组越界异常,现更正如下:

@Override

public int getCount() {

// return 100;

return data.size();

}

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值