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即可。
运行效果如下
下面是最核心的部分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,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微信开发教程汇总》,欢迎大家学习阅读。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程小技巧。
总结
如果觉得编程之家网站内容还不错,欢迎将编程之家网站推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
小编个人微信号 jb51ccc
喜欢与人分享编程技术与工作经验,欢迎加入编程之家官方交流群!
android微信列表滑动删除,Android仿微信对话列表滑动删除效果相关推荐
- 基于微信小程序开发的仿微信demo
(本文参考自github/liujians,地址:https://github.com/liujians/weApp) 作者声明: 基于微信小程序开发的仿微信demo 整合了ionic的样式库和we ...
- android 拖动控件删除,Android学习------拖动删除(仿微信朋友圈拖动删除)
1 示例 发朋友圈的时候,长按图片可以调整顺序,还可以拖动到底部删除. 2 官方示例: https://developer.android.google.cn/guide/topics/ui/drag ...
- android 调出键盘表情_android高仿微信表情输入与键盘输入代码(详细实现分析)
表情与键盘的切换输入大部分IM都会需要到,之前自己实现了一个,还是存在些缺陷,比如说键盘与表情切换时出现跳闪问题,这个困扰了我些时间,不过所幸在Github(其代码整体结构很不错)并且在论坛上找些解决 ...
- Android中使用ExpandableListView实现微信通讯录界面(完善仿微信APP)
之前的博文<Android中使用ExpandableListView实现好友分组>我简单介绍了使用ExpandableListView实现简单的好友分组功能,今天我们针对之前的所做的仿微信 ...
- Android 天气APP(十三)仿微信弹窗(右上角加号点击弹窗效果)、自定义背景图片、UI优化调整
上一篇:Android 天气APP(十二)空气质量.UI优化调整 天气预报详情,逐小时预报详情 新版------------------- 一.适配器点击监听 二.页面实现 三.天气预报详情弹窗 四. ...
- android仿微信下拉二楼_Android仿微信下拉列表实现
本文要实现微信6.1中点击顶部菜单栏的"+"号按钮时,会弹出一个列表框.这里用的了Activity实现,其实最好的方法可以用ActionBar,不过这货好像只支持3.0以后的版本. ...
- Android ActionBar应用实战,高仿微信主界面的设计
转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/26365683 经过前面两篇文章的学习,我想大家对ActionBar都已经有一个相对 ...
- 【Android App】实战项目之仿微信的私信和群聊App(附源码和演示视频 超详细必看)
需要全部代码请点赞关注收藏后评论区留言私信~~~ 手机最开始用于通话,后来增加了短信功能,初步满足了人与人之间的沟通需求.然而短信只能发文字,于是出现了能够发图片的彩信,但不管短信还是彩信,资费都太贵 ...
- Android笔记之(图片高斯+Glide实现微信图片加载策略+仿微信进度条)
很久以前就想自己实现一下仿微信图片加载的那种策略了,先加载一张模糊的图片,然后再加载清晰大图,今天研究了一下,不过要是Glide支持进度条显示就好了,不得不说Glide很强大, 不啰嗦了,直接上代码了 ...
- android 微信浮窗实现_Android仿微信视屏悬浮窗效果
在项目中需要对接入的腾讯云音视频,可以悬浮窗显示,悬浮窗可拖拽,并且在悬浮窗不影响其他的activity的焦点. 这个大神的文章Android基于腾讯云实时音视频仿微信视频通话最小化悬浮,他讲的是视频 ...
最新文章
- Auto Encoder用于异常检测
- 在Struts 2中实现文件上传
- 赛迪数据:2018年数据中心市场数据
- python2.6.6安装MySQL-python模块正确方法
- 计算机数学基础试题,计算机数学基础(A)综合练习
- Android 系统(123)---MTK android 常用修改点
- Python字典的操作与使用
- 关于DMA的两个小知识点
- SpringHttpInvoker解析3-客户端实现
- 计算机四级题库百度云,四级题库免费
- thinkpad解决Win8.1电源管理的方法
- 易了千明之易语言套装视频教程第四套辅助制作
- 理解无线电波极化与天线极化
- opcode php 缓存,深入理解PHP Opcode缓存原理
- 卖主机的建辉互联张磊道貌岸然骗子公司(www.zzidc.top)
- 代码行统计工具:根据命令行输入的指定目录及文件类型进行统计目录或单个文件的代码行数
- LinkedIn领英账号达到一周添加好友邀请上限后怎么办?学会这四式三招,你也能解决LinkedIn领英账号添加好友的每周数量限制...
- 电脑使用技巧(office 套件英文版切换为中文)
- docker查看mysql日志_Docker 容器日志分析
- python 批量云盘保存_批量保存云盘链接的deom