只需要修改 RecyclerView 支持侧滑
在ietm布局 超出屏幕的地方添加自己的删除按钮就可以
此方法入侵程度低 容易修改


import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.Scroller;import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;/*** 支持侧滑删除的RecyclerView*/public class SwipeRecyclerView extends RecyclerView {private static final String TAG = "SwipeRecyclerView";private static final int INVALID_POSITION = -1; // 触摸到的点不在子View范围内private static final int INVALID_CHILD_WIDTH = -1;  // 子ItemView不含两个子Viewprivate static final int SNAP_VELOCITY = 600;   // 最小滑动速度private VelocityTracker mVelocityTracker;   // 速度追踪器private int mTouchSlop; // 认为是滑动的最小距离(一般由系统提供)private Rect mTouchFrame;   // 子View所在的矩形范围private Scroller mScroller;private float mLastX;   // 滑动过程中记录上次触碰点Xprivate float mFirstX, mFirstY; // 首次触碰范围private boolean mIsSlide;   // 是否滑动子Viewprivate ViewGroup mFlingView;   // 触碰的子Viewprivate int mPosition;  // 触碰的view的位置private int mMenuViewWidth;    // 菜单按钮宽度public SwipeRecyclerView(Context context) {this(context, null);}public SwipeRecyclerView(Context context, @Nullable AttributeSet attrs) {this(context, attrs, 0);}public SwipeRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();mScroller = new Scroller(context);}@Overridepublic boolean onInterceptTouchEvent(MotionEvent e) {int x = (int) e.getX();int y = (int) e.getY();obtainVelocity(e);switch (e.getAction()) {case MotionEvent.ACTION_DOWN:if (!mScroller.isFinished()) {  // 如果动画还没停止,则立即终止动画mScroller.abortAnimation();}mFirstX = mLastX = x;mFirstY = y;mPosition = pointToPosition(x, y);  // 获取触碰点所在的positionif (mPosition != INVALID_POSITION) {View view = mFlingView;// 获取触碰点所在的viewmFlingView = (ViewGroup) getChildAt(mPosition - ((LinearLayoutManager) getLayoutManager()).findFirstVisibleItemPosition());// 这里判断一下如果之前触碰的view已经打开,而当前碰到的view不是那个view则立即关闭之前的view,此处并不需要担动画没完成冲突,因为之前已经abortAnimationif (view != null && mFlingView != view && view.getScrollX() != 0) {view.scrollTo(0, 0);}// 这里进行了强制的要求,RecyclerView的子ViewGroup必须要有2个子view,这样菜单按钮才会有值,// 需要注意的是:如果不定制RecyclerView的子View,则要求子View必须要有固定的width。// 比如使用LinearLayout作为根布局,而content部分width已经是match_parent,此时如果菜单view用的是wrap_content,menu的宽度就会为0。if (mFlingView.getChildCount() == 2) {mMenuViewWidth = mFlingView.getChildAt(1).getWidth();} else {mMenuViewWidth = INVALID_CHILD_WIDTH;}}break;case MotionEvent.ACTION_MOVE:mVelocityTracker.computeCurrentVelocity(1000);// 此处有俩判断,满足其一则认为是侧滑:// 1.如果x方向速度大于y方向速度,且大于最小速度限制;// 2.如果x方向的侧滑距离大于y方向滑动距离,且x方向达到最小滑动距离;float xVelocity = mVelocityTracker.getXVelocity();float yVelocity = mVelocityTracker.getYVelocity();if (Math.abs(xVelocity) > SNAP_VELOCITY && Math.abs(xVelocity) > Math.abs(yVelocity)|| Math.abs(x - mFirstX) >= mTouchSlop&& Math.abs(x - mFirstX) > Math.abs(y - mFirstY)) {mIsSlide = true;return true;}break;case MotionEvent.ACTION_UP:releaseVelocity();break;default:break;}return super.onInterceptTouchEvent(e);}@Overridepublic boolean onTouchEvent(MotionEvent e) {if (mIsSlide && mPosition != INVALID_POSITION) {float x = e.getX();obtainVelocity(e);switch (e.getAction()) {case MotionEvent.ACTION_DOWN:   // 因为没有拦截,所以不会被调用到break;case MotionEvent.ACTION_MOVE:// 随手指滑动if (mMenuViewWidth != INVALID_CHILD_WIDTH) {float dx = mLastX - x;if (mFlingView.getScrollX() + dx <= mMenuViewWidth&& mFlingView.getScrollX() + dx > 0) {mFlingView.scrollBy((int) dx, 0);}mLastX = x;}break;case MotionEvent.ACTION_UP:if (mMenuViewWidth != INVALID_CHILD_WIDTH) {int scrollX = mFlingView.getScrollX();mVelocityTracker.computeCurrentVelocity(1000);// 此处有两个原因决定是否打开菜单:// 1.菜单被拉出宽度大于菜单宽度一半;// 2.横向滑动速度大于最小滑动速度;// 注意:之所以要小于负值,是因为向左滑则速度为负值if (mVelocityTracker.getXVelocity() < -SNAP_VELOCITY) {    // 向左侧滑达到侧滑最低速度,则打开mScroller.startScroll(scrollX, 0, mMenuViewWidth - scrollX, 0, Math.abs(mMenuViewWidth - scrollX));} else if (mVelocityTracker.getXVelocity() >= SNAP_VELOCITY) {  // 向右侧滑达到侧滑最低速度,则关闭mScroller.startScroll(scrollX, 0, -scrollX, 0, Math.abs(scrollX));} else if (scrollX >= mMenuViewWidth / 2) { // 如果超过删除按钮一半,则打开mScroller.startScroll(scrollX, 0, mMenuViewWidth - scrollX, 0, Math.abs(mMenuViewWidth - scrollX));} else {    // 其他情况则关闭mScroller.startScroll(scrollX, 0, -scrollX, 0, Math.abs(scrollX));}invalidate();}mMenuViewWidth = INVALID_CHILD_WIDTH;mIsSlide = false;mPosition = INVALID_POSITION;releaseVelocity();  // 这里之所以会调用,是因为如果前面拦截了,就不会执行ACTION_UP,需要在这里释放追踪break;default:break;}return true;} else {// 此处防止RecyclerView正常滑动时,还有菜单未关闭closeMenu();// Velocity,这里的释放是防止RecyclerView正常拦截了,但是在onTouchEvent中却没有被释放;// 有三种情况:1.onInterceptTouchEvent并未拦截,在onInterceptTouchEvent方法中,DOWN和UP一对获取和释放;// 2.onInterceptTouchEvent拦截,DOWN获取,但事件不是被侧滑处理,需要在这里进行释放;// 3.onInterceptTouchEvent拦截,DOWN获取,事件被侧滑处理,则在onTouchEvent的UP中释放。releaseVelocity();}return super.onTouchEvent(e);}private void releaseVelocity() {if (mVelocityTracker != null) {mVelocityTracker.clear();mVelocityTracker.recycle();mVelocityTracker = null;}}private void obtainVelocity(MotionEvent event) {if (mVelocityTracker == null) {mVelocityTracker = VelocityTracker.obtain();}mVelocityTracker.addMovement(event);}public int pointToPosition(int x, int y) {int firstPosition = ((LinearLayoutManager) getLayoutManager()).findFirstVisibleItemPosition();Rect frame = mTouchFrame;if (frame == null) {mTouchFrame = new Rect();frame = mTouchFrame;}final int count = getChildCount();for (int i = count - 1; i >= 0; i--) {final View child = getChildAt(i);if (child.getVisibility() == View.VISIBLE) {child.getHitRect(frame);if (frame.contains(x, y)) {return firstPosition + i;}}}return INVALID_POSITION;}@Overridepublic void computeScroll() {if (mScroller.computeScrollOffset()) {mFlingView.scrollTo(mScroller.getCurrX(), mScroller.getCurrY());invalidate();}}/*** 将显示子菜单的子view关闭* 这里本身是要自己来实现的,但是由于不定制item,因此不好监听器点击事件,因此需要调用者手动的关闭*/public void closeMenu() {if (mFlingView != null && mFlingView.getScrollX() != 0) {mFlingView.scrollTo(0, 0);}}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/item_view"android:layout_width="match_parent"android:layout_height="@dimen/d80dp"android:orientation="horizontal"><androidx.appcompat.widget.LinearLayoutCompatandroid:id="@+id/layout_content"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><androidx.appcompat.widget.LinearLayoutCompatandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="horizontal"><TextViewandroid:id="@+id/tv_name"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentLeft="true"android:layout_centerInParent="true"android:layout_marginLeft="@dimen/d15dp"android:layout_marginTop="@dimen/d10dp"android:text="肺炎"android:textColor="@color/color_333333"android:textSize="@dimen/d14sp" /><TextViewandroid:id="@+id/tv_illness"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:layout_marginLeft="@dimen/d5dp"android:layout_marginTop="@dimen/d10dp"android:ellipsize="end"android:maxLines="1"android:text="(肺炎)"android:textColor="@color/color_666666"android:textSize="@dimen/d13sp" /></androidx.appcompat.widget.LinearLayoutCompat><TextViewandroid:id="@+id/tv_des"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="@dimen/d15dp"android:layout_marginTop="@dimen/d10dp"android:ellipsize="end"android:gravity="start"android:lines="2"android:maxLines="2"android:text="肺炎"android:textColor="@color/color_999999"android:textSize="@dimen/d13sp" /></androidx.appcompat.widget.LinearLayoutCompat><!--删除按钮--><TextViewandroid:id="@+id/tv_delete"android:layout_width="@dimen/d60dp"android:layout_height="match_parent"android:background="#FFF55030"android:gravity="center"android:text="删除"android:textColor="#FFFFFFFF"android:textSize="@dimen/d14sp" /></LinearLayout>

RecyclerView侧滑删除按钮相关推荐

  1. RecyclerView(侧滑删除)和下载文件

    @TOC 一.RecyclerView(侧滑删除) 1.SwipeLayout概念:可以支持侧滑的布局控件 常用方法 设置侧滑方式 :setMoe(SwipeLayout.show.PULLOUT) ...

  2. Android实现RecyclerView侧滑删除和长按拖拽-ItemTouchHelper

    RecyclerView这个被誉为ListView和GirdView的替代品,它的用法在之前的一篇博文中就已经讲过了,今天我们就来实现RecyclerView的侧滑删除和长按拖拽功能,实现这两个功能我 ...

  3. 自定义UITableview自带侧滑删除按钮样式 by 徐

    效果如下: 实现原理: 1.打开tableview自带的侧滑删除功能 核心代码: 1 -(void)tableView:(UITableView *)tableView commitEditingSt ...

  4. android.support.v7 fragme,打造最强RecyclerView侧滑菜单,长按拖拽Item,滑动删除Item

    前几天写了一片关于RecyclerView滑动删除Item,RecyclerView长按拖拽Item的博客,本来很简单一个使用,阅读量还挺高的,原博客传送门. 今天介绍一个RecyclerView I ...

  5. Android之侧滑删除RecyclerView

    前段时间做项目,有一个需求是需要做一个侧滑删除的功能. 之前由于项目赶的比较紧,所以一起工作的小伙伴用了第三方的,自己想想,这个应该不难实现. 废话不多说,先上效果图 今天权当做下笔记,这篇文章主要参 ...

  6. android allapp图标拖动,RecyclerView 拖拽移动,长按小图标拖拽,侧滑删除

    RecyclerView拖拽移动,长按小图标拖拽,侧滑删除 长按小图标拖拽.gif 侧滑删除.gif Android RecyclerView出来也很多年了,是非常成熟的控件,Github上工具一堆, ...

  7. 【Android 事件分发】ItemTouchHelper 实现侧滑删除

    Android 事件分发 系列文章目录 [Android 事件分发]事件分发源码分析 ( 驱动层通过中断传递事件 | WindowManagerService 向 View 层传递事件 ) [Andr ...

  8. java cursor 删除_使用CursorRecyclerAdatper在RecyclerView中删除和撤消

    我的recyclerview适配器加载了游标,该游标从本地数据库查询数据 . 当用户单击Viewholder布局中的删除按钮时,它将从回收器视图中删除,但在快餐栏超时之前尚未从数据库中删除 . 此按钮 ...

  9. android 仿微信侧滑删除SwipeListView实例

    原帖地址:http://www.eoeandroid.com/thread-540337-1-1.html Android微信5.0以前某个版本(具体哪个忘记了)实现了和IOS上面一样的效果--侧滑删 ...

  10. android 侧滑删除功能,200行代码让你在Android中完美实现iOS版侧滑删除效果

    使用几个月的IOS之后,发现IOS中侧滑删除俺就 大家好,自己开始学习Android已经差不多半年了吧,前前后后看了不少的博客获益匪浅.渐渐的随着技术的提升,慢慢感觉网上其它的一些功能的实现又不是那么 ...

最新文章

  1. mysql数据写入不到数据库_主机无法写入数据到Mysql数据库
  2. 牛!这位斯坦福PhD新生的论文被引数:接近4万
  3. 教你辨别36k纯数据科学家
  4. 大学哪些专业要学python_非计算机专业的大学生是否有必要学习Python编程
  5. Java并发编程的艺术,解读并发编程的优缺点
  6. 编译原理什么是移进规约冲突_我这个人不懂什么CPU,于是我用代码模拟出了一个...
  7. Java关键字new和newInstance的区别
  8. java rsa2加密算法_java RSA加密解密
  9. [渣译文] SignalR 2.0 系列: SignalR简介
  10. 分享webStorm汉化
  11. 2020年生肖码表图_2020年生肖排位表 鼠年号码岁数表
  12. 计算机信息管理专科,计算机信息管理大专简历范文
  13. CortexM3/M4(3)-指令集
  14. mac重置系统_如何在Mac上重置打印系统
  15. 【本人秃顶程序员】Java程序员,你会选择25k的996还是18k的965?
  16. 安装MongoDB出现 service MongoDB failed to start,verify that you have sufficient privileges to start
  17. mysql多表联合查询 去重_mysql中的多表联合并且去重排序
  18. linux trac svn,Ubuntu安装Trac SVN
  19. 当当网创始人李国庆宣布离开当当,投身区块链再创业
  20. 单片机c语言 〉〉,PìC单片机C语言编程入门(课件).doc

热门文章

  1. IOS开发之——图片裁剪(82)
  2. 1分钟了解 rap2
  3. 一文详解SQL关联子查询
  4. quick-cocos2dx3.5 mac模拟器改进
  5. 基于SMTP协议的E-MAIL电子邮件发送客户端软件C#实现
  6. Unity5.x从入门到精通资源(电子版+书内项目)
  7. Grid-based RRP/基于网格的路径重新规划问题
  8. 机房收费系统心得总结
  9. Android 检测手机是否是异形屏,刘海屏,水滴屏,挖孔屏
  10. NodeJs视频教程 NodeJs零基础实战视频教程-来自三人行慕课