Android仿QQ列表左滑删除操作
发布时间 - 2026-01-10 21:50:56 点击率:次最近学习了如何做一个像QQ的左滑RecyclerView的item显示选项的,主要是用到Scroller

我们首先新建一个自己的RecyclerView
定义好一些要用的的变量
重写构造方法,把前两个构造方法改为如下,使无论如何构造都要执行第三个构造方法
在第三个构造方法里初始化Scroller
public class LeftSwipeMenuRecyclerView extends RecyclerView {
//置顶按钮
private TextView tvTop;
//删除按钮
private TextView tvDelete;
//item相应的布局
private LinearLayout mItemLayout;
//菜单的最大宽度
private int mMaxLength;
//上一次触摸行为的x坐标
private int mLastX;
//上一次触摸行为的y坐标
private int mLastY;
//当前触摸的item的位置
private int mPosition;
//是否在垂直滑动列表
private boolean isDragging;
//item是在否跟随手指移动
private boolean isItemMoving;
//item是否开始自动滑动
private boolean isStartScroll;
//左滑菜单状态 0:关闭 1:将要关闭 2:将要打开 3:打开
private int mMenuState;
private static int MENU_CLOSED = 0;
private static int MENU_WILL_CLOSED = 1;
private static int MENU_OPEN = 2;
private static int MENU_WILL_OPEN = 3;
//实现弹性滑动,恢复
private Scroller mScroller;
//item的事件监听
private OnItemActionListener mListener;
public LeftSwipeMenuRecyclerView(Context context) {
this(context, null);
}
public LeftSwipeMenuRecyclerView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public LeftSwipeMenuRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mScroller = new Scroller(context, new LinearInterpolator());
}
重写onTouchEvent方法
event主要有以下几个Action
- ACTION_DOWN 手指接触到屏幕
- ACTION_MOVE 手指在屏幕滑动
- ACTION_UP 手指离开屏幕
一开始肯定要获取x和y的相对坐标
int x= (int) event.getX(); int y= (int) event.getY();
然后接下来分别处理3个不同的行为
1.ACTION_DOWN
case MotionEvent.ACTION_DOWN:
if (mMenuState == MENU_CLOSED) {
//根据坐标获得view
View view = findChildViewUnder(x, y);
if (view == null) {
return false;
}
//获得这个view的ViewHolder
RVAdapter.Holder holder = (RVAdapter.Holder) getChildViewHolder(view);
//获得这个view的position
mPosition = holder.getAdapterPosition();
//获得这个view的整个布局
mItemLayout = holder.llLayout;
//获得这个view的删除按钮
tvDelete = holder.tvDelete;
//这个view的整个置顶按钮
tvTop = holder.tvTop;
//两个按钮的宽度
mMaxLength = tvDelete.getWidth() + tvTop.getWidth();
//设置删除按钮点击监听
tvDelete.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
mItemLayout.scrollTo(0, 0);
mMenuState =MENU_CLOSED;
mListener.OnItemDelete(mPosition);
}
});
//设置置顶按钮点击监听
tvTop.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
mItemLayout.scrollTo(0, 0);
mMenuState =MENU_CLOSED;
mListener.OnItemTop(mPosition);
}
});
//如果是打开状态,点击其他就把当前menu关闭掉
} else if (mMenuState == MENU_OPEN) {
mScroller.startScroll(mItemLayout.getScrollX(), 0, -mMaxLength, 0, 200);
invalidate();
mMenuState = MENU_CLOSED;
//该点击无效
return false;
} else {
return false;
}
break;
2.ACTION_MOVE
case MotionEvent.ACTION_MOVE:
//计算偏移量
int dx = mLastX - x;
int dy = mLastY - y;
//当前滑动的x
int scrollx = mItemLayout.getScrollX();
if (Math.abs(dx) > Math.abs(dy)) {
isItemMoving = true;
//超出左边界则始终保持不动
if (scrollx + dx <= 0) {
mItemLayout.scrollTo(0, 0);
//滑动无效
return false;
//超出右边界则始终保持不动
} else if (scrollx + dx >= mMaxLength) {
mItemLayout.scrollTo(mMaxLength, 0);
//滑动无效
return false;
}
//菜单随着手指移动
mItemLayout.scrollBy(dx, 0);
//如果水平移动距离大于30像素的话,recyclerView不会上下滑动
}else if (Math.abs(dx) > 30){
return true;
}
//如果菜单正在打开就不能上下滑动
if (isItemMoving){
mLastX = x;
mLastY = y;
return true;
}
break;
3.ACTION_UP
case MotionEvent.ACTION_UP:
//手指抬起时判断是否点击,静止且有Listener才能点击
if (!isItemMoving && !isDragging && mListener != null) {
mListener.OnItemClick(mPosition);
}
isItemMoving = false;
//等一下要移动的距离
int deltaX = 0;
int upScrollx = mItemLayout.getScrollX();
//滑动距离大于1/2menu长度就自动展开,否则就关掉
if (upScrollx >= mMaxLength / 2) {
deltaX = mMaxLength - upScrollx;
mMenuState = MENU_WILL_OPEN;
} else if (upScrollx < mMaxLength / 2) {
deltaX = -upScrollx;
mMenuState = MENU_WILL_CLOSED;
}
//知道我们为什么不直接把mMenuState赋值为MENU_OPEN或者MENU_CLOSED吗?因为滑动时有时间的,我们可以在滑动完成时才把状态改为已经完成
mScroller.startScroll(upScrollx, 0, deltaX, 0, 200);
isStartScroll = true;
//刷新界面
invalidate();
break;
之后还要在onTouchEvent方法里刷新坐标
//只有更新mLastX,mLastY数据才会准确
mLastX = x;
mLastY = y;
return super.onTouchEvent(e);
因为我们用到了startScroll所以要重写computeScroll方法
public void computeScroll() {
//判断scroller是否完成滑动
if (mScroller.computeScrollOffset()) {
mItemLayout.scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
//这个很重要
invalidate();
//如果已经完成就改变状态
} else if (isStartScroll) {
isStartScroll = false;
if (mMenuState == MENU_WILL_CLOSED) {
mMenuState = MENU_CLOSED;
}
if (mMenuState == MENU_WILL_OPEN) {
mMenuState = MENU_OPEN;
}
}
}
**还要监听RecyclerView是否在上下滑动
@Override
public void onScrollStateChanged(int state) {
super.onScrollStateChanged(state);
//是否在上下滑动
isDragging = state == SCROLL_STATE_DRAGGING;
}
还要设置Listener
//设置Listener
public void setOnItemActionListener(OnItemActionListener onItemActionListener) {
this.mListener = onItemActionListener;
}
这个Listener是要自己新建的
public interface OnItemActionListener {
void OnItemClick(int position);
void OnItemTop(int position);
void OnItemDelete(int position);
}
最后是点击,置顶,删除在Activity里的回调
这里只展示回调实现部分,我这里用的List是LinkedList,可以在第一位添加数据
rv.setOnItemActionListener(new OnItemActionListener() {
//点击
@Override
public void OnItemClick(int position) {
Toast.makeText(MainActivity.this,"Click"+position,Toast.LENGTH_SHORT).show();
}
//置顶
@Override
public void OnItemTop(int position) {
//获得当前位置的内容
String temp =list.get(position);
//移除这个item
list.remove(position);
//把它添加到第一个
list.addFirst(temp);
//更新数据源
adapter.notifyDataSetChanged();
}
//删除
@Override
public void OnItemDelete(int position) {
list.remove(position);
//更新数据源
adapter.notifyDataSetChanged();
}
});
Adapter和布局的代码太简单我就不放出来了,大家可以到源码里看看有什么
效果图
源码地址:https://github.com/jkgeekJack/SlideLeftMenuRecyclerView
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
# Android仿QQ列表左滑删除
# Android仿QQ列表
# Android左滑删除
# Android高仿QQ6.0侧滑删除实例代码
# 详解Android中实现ListView左右滑动删除条目的方法
# android RecyclerView侧滑菜单
# 滑动删除
# 长按拖拽
# 下拉刷新上拉加载
# Android仿微信滑动弹出编辑、删除菜单效果、增加下拉刷新功能
# Android实现左滑删除列表功能
# Android 实现左滑出现删除选项
# Android使用CardView作为RecyclerView的Item并实现拖拽和左滑删除
# Android 滑动监听RecyclerView线性流+左右划删除+上下移动
# Android开发中模仿qq列表信息滑动删除功能
# Android Recyclerview实现左滑删除功能
# 置顶
# 重写
# 不动
# 第三个
# 回调
# 始终保持
# 自己的
# 有什么
# 几个
# 我就
# 是在
# 都要
# 才会
# 我这
# 把它
# 要在
# 我们可以
# 就把
# 要用
# 很重要
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
Mybatis 中的insertOrUpdate操作
高端企业智能建站程序:SEO优化与响应式模板定制开发
瓜子二手车官方网站在线入口 瓜子二手车网页版官网通道入口
Laravel如何处理JSON字段_Eloquent原生JSON字段类型操作教程
手机网站制作平台,手机靓号代理商怎么制作属于自己的手机靓号网站?
Laravel如何获取当前登录用户信息_Laravel Auth门面使用与Session用户读取【技巧】
5种Android数据存储方式汇总
惠州网站建设制作推广,惠州市华视达文化传媒有限公司怎么样?
php结合redis实现高并发下的抢购、秒杀功能的实例
Laravel如何生成PDF或Excel文件_Laravel文档导出工具与使用教程
Laravel Eloquent访问器与修改器是什么_Laravel Accessors & Mutators数据处理技巧
Laravel如何处理表单验证?(Requests代码示例)
如何快速启动建站代理加盟业务?
UC浏览器如何切换小说阅读源_UC浏览器阅读源切换【方法】
Laravel storage目录权限问题_Laravel文件写入权限设置
如何在云主机上快速搭建多站点网站?
通义万相免费版怎么用_通义万相免费版使用方法详细指南【教程】
,网页ppt怎么弄成自己的ppt?
Google浏览器为什么这么卡 Google浏览器提速优化设置步骤【方法】
Claude怎样写结构化提示词_Claude结构化提示词写法【教程】
北京企业网站设计制作公司,北京铁路集团官方网站?
如何为不同团队 ID 动态生成多个“认领值班”按钮
iOS验证手机号的正则表达式
Bootstrap整体框架之CSS12栅格系统
如何在自有机房高效搭建专业网站?
微博html5版本怎么弄发超话_超话进入入口及发帖格式要求【教程】
Laravel怎么做数据加密_Laravel内置Crypt门面的加密与解密功能
javascript中的数组方法有哪些_如何利用数组方法简化数据处理
ai格式如何转html_将AI设计稿转换为HTML页面流程【页面】
关于BootStrap modal 在IOS9中不能弹出的解决方法(IOS 9 bootstrap modal ios 9 noticework)
JavaScript如何实现继承_有哪些常用方法
手机网站制作与建设方案,手机网站如何建设?
详解Android中Activity的四大启动模式实验简述
哪家制作企业网站好,开办像阿里巴巴那样的网络公司和网站要怎么做?
Laravel如何使用缓存系统提升性能_Laravel缓存驱动和应用优化方案
nodejs redis 发布订阅机制封装实现方法及实例代码
Win11怎么关闭专注助手 Win11关闭免打扰模式设置【操作】
标题:Vue + Vuex 项目中正确使用 JWT 进行身份认证的实践指南
在线制作视频的网站有哪些,电脑如何制作视频短片?
javascript中数组(Array)对象和字符串(String)对象的常用方法总结
laravel怎么用DB facade执行原生SQL查询_laravel DB facade原生SQL执行方法
今日头条AI怎样推荐抢票工具_今日头条AI抢票工具推荐算法与筛选【技巧】
如何用5美元大硬盘VPS安全高效搭建个人网站?
如何在宝塔面板中修改默认建站目录?
如何在服务器上配置二级域名建站?
如何在阿里云ECS服务器部署织梦CMS网站?
微信小程序 scroll-view组件实现列表页实例代码
悟空识字怎么关闭自动续费_悟空识字取消会员自动扣费步骤
Laravel的契約(Contracts)是什么_深入理解Laravel Contracts与依赖倒置
Laravel怎么设置路由分组Prefix_Laravel多级路由嵌套与命名空间隔离【步骤】

