【Android】实现Recyclerview的Item可以左右侧滑动的效果

embedded/2024/10/18 7:53:16/
项目需要

使用Recyclerview进行列表的数据加载的时候,需要对这个Item进行左右滑动进行操作的功能,
比如这样
在这里插入图片描述
在这里插入图片描述

需求实现

上面图来源于
https://github.com/anzaizai/EasySwipeMenuLayout
这是一个可以用来进行列表左滑、右滑的项目,可以集成到自己的项目中

compile 'com.github.anzaizai:EasySwipeMenuLayout:1.1.4'

推荐搭配Brvah框架使用

api 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.49'

使用方式业非常简单
例如

        <com.guanaj.easyswipemenulibrary.EasySwipeMenuLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"app:contentView="@+id/content"app:leftMenuView="@+id/left"app:rightMenuView="@+id/right"><LinearLayoutandroid:id="@+id/left"android:layout_width="100dp"android:layout_height="wrap_content"android:background="@android:color/holo_blue_dark"android:orientation="horizontal"android:padding="20dp"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="分享" /></LinearLayout><LinearLayoutandroid:id="@+id/content"android:layout_width="match_parent"android:layout_height="wrap_content"android:background="#cccccc"android:orientation="vertical"android:padding="20dp"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="内容区域" /></LinearLayout><LinearLayoutandroid:id="@+id/right"android:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@android:color/holo_red_light"android:orientation="horizontal"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@android:color/holo_blue_bright"android:padding="20dp"android:text="删除" /><TextViewandroid:id="@+id/right_menu_2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@android:color/holo_orange_dark"android:padding="20dp"android:text="收藏" /></LinearLayout></com.guanaj.easyswipemenulibrary.EasySwipeMenuLayout>
    public class MyAdapter extends BaseQuickAdapter<String, BaseViewHolder> {public MyAdapter(@LayoutRes int layoutResId, @Nullable List<String> data) {super(layoutResId, data);}@Overrideprotected void convert(final BaseViewHolder helper, String item) {helper.getView(R.id.right_menu_2).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Toast.makeText(MainActivity.this, "收藏", Toast.LENGTH_SHORT).show();EasySwipeMenuLayout easySwipeMenuLayout = helper.getView(R.id.es);easySwipeMenuLayout.resetStatus();}});helper.getView(R.id.content).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Toast.makeText(MainActivity.this, "setOnClickListener", Toast.LENGTH_SHORT).show();}});}}

按照这个Demo上面讲的,这样基本上就可以了,但是有问题需要注意:

使用这个框架之后,虽然实现了左右滑动显示不用的按钮的效果,但是这个整个Item的点击事件是被拦截了,这就导致

//        rvAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
//            @Override
//            public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
//
//            }
//        });

这个方法是失效的,要是对这个没有什么需求的话这个可以不用管,但是我们要是对某一个Item进行操作的时候,怎么获得这个position呢?
需要这样做

 helper.getView(R.id.content).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Toast.makeText(MainActivity.this, "setOnClickListener", Toast.LENGTH_SHORT).show();
//在这个方法里面,因为此方法在【convert】里面,所以可以在这里获取到我们需要的positionint pos = helper.getAdapterPosition();//这样就可以操作了}});

但是有时候我们的页面要复用,需要这个点击事件的时候,这个时候该怎么办呢,这个时候就要修改这个代码了,修改的地方不多

首先我们需要在github上面把这个项目下载下来,把里面的代码放到我们项目中,代码很少,我们在这个【EasySwipeMenuLayout】里面
加入一个字段

 private boolean isNeedClick = false; //是否需要(非滑动之后的)点击事件
    public boolean isNeedClick() {return isNeedClick;}public void setNeedClick(boolean needClick) {isNeedClick = needClick;}

然后在里面的【dispatchTouchEvent】和【onInterceptTouchEvent】方法里面加入

    if (isNeedClick()) {return super.dispatchTouchEvent(ev);}

    if (isNeedClick()) {return super.onInterceptTouchEvent(event);}

全部代码如下

 @Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {if (isNeedClick()) {return super.dispatchTouchEvent(ev);}switch (ev.getAction()) {case MotionEvent.ACTION_DOWN: {//   System.out.println(">>>>dispatchTouchEvent() ACTION_DOWN");isSwipeing = false;if (mLastP == null) {mLastP = new PointF();}mLastP.set(ev.getRawX(), ev.getRawY());if (mFirstP == null) {mFirstP = new PointF();}mFirstP.set(ev.getRawX(), ev.getRawY());if (mViewCache != null) {if (mViewCache != this) {mViewCache.handlerSwipeMenu(State.CLOSE);}// Log.i(TAG, ">>>有菜单被打开");getParent().requestDisallowInterceptTouchEvent(true);}break;}case MotionEvent.ACTION_MOVE: {//   System.out.println(">>>>dispatchTouchEvent() ACTION_MOVE getScrollX:" + getScrollX());float distanceX = mLastP.x - ev.getRawX();float distanceY = mLastP.y - ev.getRawY();if (Math.abs(distanceY) > mScaledTouchSlop && Math.abs(distanceY) > Math.abs(distanceX)) {break;}
//                if (Math.abs(distanceX) <= mScaledTouchSlop){
//                    break;
//                }// Log.i(TAG, ">>>>>distanceX:" + distanceX);scrollBy((int) (distanceX), 0);//滑动使用scrollBy//越界修正if (getScrollX() < 0) {if (!mCanRightSwipe || mLeftView == null) {scrollTo(0, 0);} else {//左滑if (getScrollX() < mLeftView.getLeft()) {scrollTo(mLeftView.getLeft(), 0);}}} else if (getScrollX() > 0) {if (!mCanLeftSwipe || mRightView == null) {scrollTo(0, 0);} else {if (getScrollX() > mRightView.getRight() - mContentView.getRight() - mContentViewLp.rightMargin) {scrollTo(mRightView.getRight() - mContentView.getRight() - mContentViewLp.rightMargin, 0);}}}//当处于水平滑动时,禁止父类拦截if (Math.abs(distanceX) > mScaledTouchSlop
//                        || Math.abs(getScrollX()) > mScaledTouchSlop) {//  Log.i(TAG, ">>>>当处于水平滑动时,禁止父类拦截 true");getParent().requestDisallowInterceptTouchEvent(true);}mLastP.set(ev.getRawX(), ev.getRawY());break;}case MotionEvent.ACTION_UP:case MotionEvent.ACTION_CANCEL: {//     System.out.println(">>>>dispatchTouchEvent() ACTION_CANCEL OR ACTION_UP");finalyDistanceX = mFirstP.x - ev.getRawX();if (Math.abs(finalyDistanceX) > mScaledTouchSlop) {//  System.out.println(">>>>P");isSwipeing = true;}result = isShouldOpen(getScrollX());handlerSwipeMenu(result);break;}default: {break;}}return super.dispatchTouchEvent(ev);}
@Overridepublic boolean onInterceptTouchEvent(MotionEvent event) {if (isNeedClick()) {return super.onInterceptTouchEvent(event);}//  Log.d(TAG, "<<<<dispatchTouchEvent() called with: " + "ev = [" + event + "]");switch (event.getAction()) {case MotionEvent.ACTION_DOWN: {break;}case MotionEvent.ACTION_MOVE: {//滑动时拦截点击时间if (Math.abs(finalyDistanceX) > mScaledTouchSlop) {// 当手指拖动值大于mScaledTouchSlop值时,认为应该进行滚动,拦截子控件的事件//   Log.i(TAG, "<<<onInterceptTouchEvent true");return true;}
//                if (Math.abs(finalyDistanceX) > mScaledTouchSlop || Math.abs(getScrollX()) > mScaledTouchSlop) {
//                    Log.d(TAG, "onInterceptTouchEvent: 2");
//                    return true;
//                }break;}case MotionEvent.ACTION_UP:case MotionEvent.ACTION_CANCEL: {//滑动后不触发contentView的点击事件if (isSwipeing) {isSwipeing = false;finalyDistanceX = 0;return true;}}}return super.onInterceptTouchEvent(event);}

然后我们在Adapter里面

            if (helper.getView(R.id.easy_swipe_ly) instanceof EasySwipeMenuLayout) {((EasySwipeMenuLayout) helper.getView(R.id.easy_swipe_ly)).setNeedClick(true);}

这样就可以了,但是需要注意的是,如果这样设置了,我们的左右滑动就失效了,但是点击事件生效了。需要根据具体需求自行设置。


http://www.ppmy.cn/embedded/48589.html

相关文章

C# WPF入门学习主线篇(三十二)—— 创建Model、View和ViewModel

C# WPF入门学习主线篇&#xff08;三十二&#xff09;—— 创建Model、View和ViewModel 在前一篇文章中&#xff0c;我们介绍了MVVM&#xff08;Model-View-ViewModel&#xff09;模式的基本概念。本篇将深入探讨如何在实际开发中创建Model、View和ViewModel&#xff0c;并通过…

B+索引的分裂及选择率和索引基数

1、B树索引的分裂 B树索引页的分裂并不总是从页的中间记录开始&#xff0c;这样可能会导致页空间的浪费。 例子 比如下面这个记录&#xff1a; 1、2、3、4、5、6、7、8、9 由于插入是以自增的顺序进行的&#xff0c;若这时插入第10条记录然后进行页的分裂操作&#xff0c;那…

代码解读 | Hybrid Transformers for Music Source Separation[06]

一、背景 0、Hybrid Transformer 论文解读 1、代码复现|Demucs Music Source Separation_demucs架构原理-CSDN博客 2、Hybrid Transformer 各个模块对应的代码具体在工程的哪个地方 3、Hybrid Transformer 各个模块的底层到底是个啥&#xff08;初步感受&#xff09;&#xff1…

Ceph入门到精通-Crimson 和 Classic Ceph OSD 架构之间的区别

Crimson 和 Classic Ceph OSD 架构之间的区别 在典型的 ceph-osd 架构中,messenger 线程从 wire 读取客户端消息,它将消息放在 OP 队列中。然后,osd-op thread-pool 会提取消息,并创建一个事务并将其排队到 BlueStore,当前的默认 ObjectStore 实现。然后,BlueStore 的 k…

Vue项目中,利用iframe在线预览pdf/图片等

在components下新建 src\components\iFrame\index.vue <template><div v-loading"loading" :style"height: height"><iframe :src"src" frameborder"no" style"width: 100%; height: 100%" scrolling"…

江苏哪些行业需要服务器托管?

服务器托管顾名思义就是用户委托具有完善设备的机房、良好网络和丰富运营经验的服务商管理其计算机系统&#xff0c;使企业的服务器能够更加安全、稳定和高效的运行&#xff0c;那在江苏都有哪些行业需要服务器托管服务呢&#xff1f;本文就来大概介绍一下。 首先让我们来一起了…

u盘数据要在哪台电脑上恢复?u盘数据恢复后保存在哪里

在数字化时代&#xff0c;U盘已成为我们日常生活中不可或缺的数据存储设备。然而&#xff0c;由于各种原因&#xff0c;U盘中的数据可能会意外丢失&#xff0c;这时数据恢复就显得尤为重要。但是&#xff0c;很多人对于在哪台电脑上进行U盘数据恢复以及恢复后的数据应保存在哪里…

Pod中使用自定义服务账号调用自定义资源

一、背景 1、从开发角度 &#xff08;1&#xff09;服务通过容器化部署的方式运行在云环境的Pod中&#xff0c;然而在 Kubernetes 中&#xff0c;Pod 中的服务不能直接通过 client-go 访问 Kubernetes 资源&#xff0c;而是需要通过 Kubernetes API Server 来进行访问。clien…