跨多个RecyclerView拖动排序

仿任务面板 跨多个RecyclerView的Item拖动 支持缩小后拖动 点击关注了解更多精彩内容!!魏子翔,2017年加入去哪儿网技术团队,目前在平台事业部/大前端技术中心,主要负责Android平台的基础框架和跨端混合应用方向研发。关注前沿... 阅读详情
先介绍一下本文出现的背景,项目中有这样一个需求,拖动一个列表的某一项排序或者拖动到另外一个列表中。

其效果如下图:

这里写图片描述

拖动排序在RecyclerView有现成的解决方案,配合ItemTouchHelper即可轻松实现。但是要将一个列表中的Item拖动到另一个列表中去,就不那么容易了。

先来看看这种跨界面实现由那些难点,我们先分析,再一个一个的解决。

  • 拖动视图的保存,ItemTouchHelper的实现思路是获取到长按的View后,对这个View做Translate位移,但是这样做的局限在于这个View就只能在它所属的RecyclerView中移动,超出的部分就被隐藏了。
  • 当拖动Item到边缘后,两个界面怎么切换,是使用系统的ViewPager还是自定义ViewGroup。
  • 在一个RecyclerView中拖动和跨多个拖动用到的策略是否一样。
  • 由于RecyclerView已经接收了触摸事件,那么怎么获取触摸信息,比如判断滑到边缘了,以及Item是否长按。

现在我们来一个一个的解决上面的问题:
1. 对于第一个问题,解决方法是当判断Item被长按后,将当前Item记录为一张图片,然后设置给一个隐藏的ImageView,对这个ImageView做Translate平移。这里需要额外费心的是这个ImageView与长按Item视图的重合以及显隐判断。
2. 如果使用ViewPager,由于要跨越两个page,那么触摸事件,保存的图片等都要交给其父控制器,还不如自定义一个ViewGroup。
3. 由于系统提供了在一个RecyclerView中拖动的Helper类,我们无需去解决拖动的起始位置这些,那何乐不为呢?所以,跨界面拖动用自己的实现。
4. 触摸point信息的获取:dispatchTouchEvent方法是最先到的,在我们自定义的ViewPager中重写该方法。在adapter中对itemview添加手势监听,获取到被长按的View。

下面来看代码实现:

(1) 自定义的父视图:

public class NewLinearLayout extends LinearLayout {

    /*将触摸点坐标传递出去*/
    private IGetX iGetX;
    /*弹性滑动*/
    private Scroller mScroller;

    public NewLinearLayout(Context context) {
        super(context);
        init(context);
    }

    public NewLinearLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public NewLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    /*initial*/
    public void init(Context context){
        mScroller = new Scroller(context);
    }

    @Override
    public void computeScroll(){
        super.computeScroll();
        /*判断是否完成滑动*/
        if(mScroller.computeScrollOffset()){
            scrollTo(mScroller.getCurrX() , 0);
            /*循环调用该方法*/
            postInvalidate();
        }
    }

    /*开启弹性滑动*/
    public void beginScroll(int dx ){
        mScroller.startScroll(mScroller.getCurrX() , 0 , dx , 0 , 1000);
        /*调用computeScroll()方法*/
        invalidate();
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event){
        float dx = event.getX();
        float dy = event.getY();
        if(event.getAction() == MotionEvent.ACTION_MOVE)
            iGetX.point(dx , dy);
        return super.dispatchTouchEvent(event);
    }

    public void set(IGetX iGetX){
        this.iGetX = iGetX;
    }

    public interface IGetX{
        void point(float dx , float dy);
    }
}

(2) View转bitmap

    public Bitmap view2bitmap(View view) {
        int width = view.getMeasuredWidth();
        int height = view.getMeasuredHeight();
        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        view.draw(new Canvas(bitmap));
        return bitmap;
    }

(3) Adapter的实现

    private class Recycler1Adapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

        private ArrayList<String> mData;

        public void setData(ArrayList<String> mData) {
            this.mData = mData;
        }

        public void addData(ArrayList<String> mData) {
            this.mData.addAll(mData);
            notifyDataSetChanged();
        }

        @Override
        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View itemView = LayoutInflater.from(SpanDragActivity.this).inflate(R.layout.item_launch_title, null);
            final Recycler1ViewHolder viewHolder = new Recycler1ViewHolder(itemView);
            viewHolder.itemView.setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    mDetector.onTouchEvent(event);
                    if(event.getAction() == MotionEvent.ACTION_DOWN){
                        bitmap = null;
                        TempItemView = viewHolder.itemView;
                        startX = TempItemView.getLeft();
                        startY = TempItemView.getTop();
                    }
                    /*恢复计点*/
                    if(event.getAction() == MotionEvent.ACTION_UP){
                        isFirstPoint = true;
                    }

                    return false;
                }
            });
            return viewHolder;
        }

        @Override
        public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
            ((Recycler1ViewHolder) holder).mTv.setText(mData.get(position));
        }

        @Override
        public int getItemCount() {
            return mData.size();
        }

        /*create viewholder*/
        class Recycler1ViewHolder extends RecyclerView.ViewHolder {

            private TextView mTv;

            public Recycler1ViewHolder(View itemView) {
                super(itemView);
                mTv = (TextView) itemView.findViewById(R.id.item_launch_title_tv_title);
            }
        }
    }

(4) 滑动到边缘后触发的事件

        /*设置接口获取手指位置*/
        activitySpanLl.set(new NewLinearLayout.IGetX() {
            @Override
            public void point(float dx , float dy) {
                Log.v("out", "手指位置:" + dx);
                if(isFirstPoint){
                    firstX = dx;
                    firstY = dy;
                    isFirstPoint = false;
                }
                if(bitmap != null) {
                    activitySpanImg.setTranslationX(dx-firstX+startX);
                    activitySpanImg.setTranslationY(dy-firstY+startY);
                }
                if(dx >=800){
                }
                if (isFirstScroll)
                    if (dx >= 1000) {
                        activitySpanLl.beginScroll(1080);
                        isFirstScroll = false;
                        /*向右边滑动了,所以现在可以向左滑动了*/
                        isFirstLeftScroll = true;
                        int a = activitySpanLl.getScrollX();
                        float b = activitySpanLl.getX();
                    }
                if(isFirstLeftScroll)
                    if(dx <= 80){
                        activitySpanLl.beginScroll(-1080);
                        isFirstLeftScroll = false;
                        /*向左边滑动了,所以现在可以向右滑动了*/
                        isFirstScroll = true;
                        int a = activitySpanLl.getScrollX();
                        float b = activitySpanLl.getX();
                    }
            }
        });
基本思路和重要的代码都在上面了,在实际项目中应用还需要对坐标,滑动等作出优化。

有更多问题留言交流。

注意:
因为电脑更换,本demo源码已经找不到了,但是鉴于很多人需要,所以这周我重新写一个demo,需要的先加这个QQ群(之前由于一些原因博客停止更新,接下来会继续更新,主要是音视频相关的,也可以入群交流)

                            703660703

欢迎入群

Android:RecyclerView的滑动删除和拖动排序以及排序后的position错位问题 RecyclerView的滑动删除和拖动排序以及排序后的position错位问题 定义相关接口: public interface OnItemTouchListener { boolean onMove(int fromPosition,int toPosition); void onSwiped(int position); } 实现接口: ... 阅读详情

相关推荐

RecyclerView拖动及拖动后position错乱问题

之前在做一个App自定义顺序的功能,用户需要拖动App到自己想要的位置,刚开始一切都写好之后,拖动么有问题当排序之后发现位置完全错乱了,根本不是我们想要的顺序,所以今天就把这个坑分享出来,也给自己做个记录。   定义接口记录拖动前后的位置: public interface ItemTouchHelperAdapter { //数据交换前后位置 void onItemMo...

anyudong123的博客 4755

跨RecyclerView的拖动排序

实现需求:侧边栏有两个RecyclerView,需要拖动一个RecyclerView里面的Item项到另一个RecyclerView里面,然后触发这个RecyclerView的拖动排序。 初次实现的思路:使用RecyclerView源生的拖拽排序支持,ItemTouchHelper.Callback 实现;在Item的longclick时主动调用ItemTouchHelper.startDrag(viewHolder)触发RecyclerView的拖动排序,这样就实现了本RecyclerView的拖动排序

yinchangliu的博客 2886

Android RecyclerView拖动排序功能实现

RecyclerView是Android平台上用于展示长列表数据的强大组件。它不仅可以高效地管理大量的列表项,还可以在运行时动态地改变列表项的显示方式。本章将简单介绍RecyclerView的基本概念及其在项目中的应用,为后续章节学习如何通过ItemTouchHelper实现拖动排序功能打下基础。RecyclerView允许开发者对列表项进行水平或垂直滚动,并且可以灵活地配置不同的布局管理器,如LinearLayoutManager、GridLayoutManager等,以适应不同场景下的需求。

weixin_29717341的博客 1158

Android使用ItemTouchHelper实现RecyclerView的item拖动位置交换和侧滑删除

activity_main5.xml: item_rv.xml :

火星男孩的分享空间 935

RecyclerView拖动排序与滑动删除的ItemTouchHelper实现.zip

在Android开发中,是一个灵活且强大的组件,用于在有限的窗口中展示大量的数据集。Adapter是与数据集之间沟通的桥梁。尽管提供了这样的基础适配器来快速启动,但在许多情况下,我们需要更精细地控制的行为。自定义Adapter变得非常重要的原因有几个:数据集定制:对于特定的数据结构,标准适配器可能不能以最优的方式展示数据。视图类型多样:当我们需要在同一个中展示多种不同的数据项视图类型时,需要自定义适配器来处理。自定义交互。

weixin_42575109的博客 985

两个Recyclerview相互拖Item

两个Recyclerview之间利用View.onDragListener相互拖放item 1、从一个Recyclerview拖到另一个item 2、两个Recyclerview的item支持互换

RecyclerView实现拖动排序和滑动删除功能

RecyclerView 的拖动排序需要借助一下 ItemTouchHelper 这个类,ItemTouchHelper 类是 Google 提供的一个支持 RecyclerView 滑动和拖动的一个使用类,下面使用该类实现 RecyclerView 的滑动删除和拖动排序功能。首先大概介绍一下 ItemTouchHelper 的一个内部抽象类 Callback 类。 ItemTouchHelper

躬行之 856

多个RecycleView的item拖动

1.多个RecycleView的item拖拽, 2.添加RecycleView头部布局和脚布局 3.上拉刷新,下拉加载

【Android】RecyclerView拖动排序和侧滑删除功能实现

ItemTouchHandler 是 Google 提供的一个工具类,主要针对 RecyclerView 的上下左右拖动事件进行处理,可以同时实现拖动排序和侧滑删除功能。 第三方SwipeDelMenuLayout,毫无耦合性,一个Item根布局搞定 item侧滑删除菜单。不依赖任何父布局,不是针对 RecyclerView、ListView,而是任意的 ViewGroup 里的 childView 都可以使用侧滑删除。

full courage的博客 4142

两个Recyclerview之间利用View.onDragListener相互拖放item交换数据(Drag-on-Drop)

两个Recyclerview之间利用View.onDragListener相互拖放item交换数据(Drag-on-Drop),并且可以拖放排序,同一个Recyclerview之间利用ItemTouchHelper进行拖放排序.

tcllib2.0 package - csv

tcl lib 的csv库

shin 859

RecyclerView借助ItemTouchHelper实现拖动排序功能

想要实现项目的拖动排序功能,listview和gridivew需要复杂的计算坐标值等,recyclerview功能强大,借助itemtouchhelper可以很方便的实现拖动和侧滑等功能,重写onmove方法,数据列表索引错乱需要更新列表排序

曲幽 755

Flocking for Multi-Agent Dynamic Systems: Algorithms and Theory的理论简述和python仿真实现(附源码)

经典论文Flocking for Multi-Agent Dynamic Systems: Algorithms and Theory的学习与编程仿真,提供源码

m0_59701926的博客 1235

Android Studio recyclerview修改滑动阈值,实现半程拖动排序(ItemTouchHelper)

最近在研究recyclerview的拖动排序功能,有很多文章都介绍了,直接生成一个ItemTouchHelper实例,绑定在recyclerview上就行,非常轻松。不过,我想要实现半程拖动功能。拿支付宝的付款顺序举例(下图),初始“余额宝”在第一行,“账户余额”在第二行。当我把“余额宝”往下拖动一半时,“账户余额”就滑动到了第一行。此时我一松手,“余额宝”就会跑到第二行去。本来我以为实现起来很简单,说不定set一个参数就能做到,然而在找遍社区、问遍ai后,依然不能得到满意的结果。

weixin_49363585的博客 1381

PWM调光原理详解:为什么你的LED灯会闪烁?从硬件到软件的避坑指南

本文深入解析PWM调光原理,揭示LED灯闪烁的根本原因,并提供从硬件设计到软件算法的全面解决方案。通过分析人眼视觉暂留机制和PWM参数设置,帮助开发者避免频闪问题,提升照明质量。特别适合电子工程师和智能家居开发者参考。

weixin_29189363的博客 291

科研绘图神器Origin2024最新中文版安装教程:5分钟搞定所有配置

本文提供了一份详细的Origin2024中文版安装与配置指南。从系统环境核查、安装包获取验证,到分步安装、语言切换及关键初始设置,手把手教你5分钟完成所有基础配置。同时,指南还分享了首次启动后的个性化设置与高效绘图工作流,助你快速上手这款科研绘图神器,提升数据处理与图表制作效率。

weixin_29247219的博客 1033

Android之RecyclerView列表拖动排序

随着需求的变化,很多地方需要加拖动改变顺序的需求,用RecyclerView就可以实现列表拖动排序,列如像朋友圈图片拖动排序,或者音乐播放器列表拖动排序。实现列表拖拽排序其实很简单,RecyclerView正常加载数据,然后去设置ItemTouchHelper就可以了,是不是很简单呢。

叶已初秋的博客 823

深入IR2104数据手册:被忽略的SD引脚用法和死区时间调节实战

本文深入解析IR2104半桥驱动芯片的SD引脚用法和死区时间调节技巧,帮助硬件工程师优化电机控制和电源转换系统。通过详细的电路设计、实测数据和调试方法,揭示SD引脚的多重保护机制和死区时间的精密调节策略,提升系统安全性和效率。

weixin_30342363的博客 386

RecyclerView拖动滑动之ItemTouchHelper

ItemTouchHelper ItemTouchHelper是一个强大的工具,它处理好了关于在RecyclerView上添加拖动排序与滑动删除的所有事情。 它是RecyclerView.ItemDecoration的子类,也就是说它可以轻易的添加到几乎所有的LayoutManager和Adapter中。 它还可以和现有的item动画一起工作,提供受类型限制的拖放动画等等, 类介绍 主要...

android开发笔记 1265

手把手教你用fusb302实现PD快充:从驱动移植到实战调试(附源码)

本文详细解析了基于FUSB302芯片实现USB PD快充的完整开发流程。内容涵盖芯片选型、硬件设计要点、Linux驱动移植与内核集成,并重点剖析了PD协议交互中的关键调试技巧,如“死亡15ms”时序问题与中断模式选择。文章通过实战经验,帮助嵌入式开发者高效完成从驱动移植到系统集成的全链路开发,并附有源码参考。

sky77的博客 373

华为Watch的ECG功能技术分析

华为Watch的ECG(心电图)功能通过硬件传感器、算法优化和医疗认证的结合,实现了对心脏电活动的监测和房颤(AFib)等心律失常的预警。采用医疗级ECG模拟前端芯片(AFE),如TI(德州仪器)的ADS1292R等,支持低噪声、高采样率(通常≥200Hz)。结合PPG(光学心率)数据交叉验证,提高检测可靠性(如ECG和PPG心率不一致时触发警告)。通过RR间期变异性判断心律是否规则,识别房颤(AFib)的典型特征(如不规则不规则心律)。结合加速度计数据,识别手臂运动导致的信号失真,动态调整算法参数。

xu_wenming的博客 6435

android recyclerview多布局_RecyclerView实现拖动排序和滑动删除功能

RecyclerView 的拖动排序需要借助一下 ItemTouchHelper 这个类,ItemTouchHelper 类是 Google 提供的一个支持 RecyclerView 滑动和拖动的一个使用类,下面使用该类实现 RecyclerView 的滑动删除和拖动排序功能。首先大概介绍一下 ItemTouchHelper 的一个内部抽象类 Callback 类。 ItemTouchHelpe...

weixin_39857153的博客 588

智能能效管家:基于 ESP32 的智能插座设计与精细化功耗管理实现

针对传统插座无法远程控制、功耗监测缺失、能源浪费严重等问题,本文设计一款基于 ESP32 主控芯片的智能插座。该系统集成 WiFi 无线通信、交流功耗采集、继电器通断控制模块,实现四大核心功能。硬件采用模块化选型与安全接线设计,软件基于 Arduino-ESP32 框架开发,搭载 Mqtt 通信协议与功耗算法,可通过手机 / 云端实时管控设备,有效提升用电安全性与能源利用率。:ESP32;智能插座;功耗管理;远程控制;能耗监测。

weixin_42300449的博客 100

实现 RecyclerView 可拖动 item 排序的方法

RecyclerView 是 Android 开发中常用的列表控件,但有时需要对列表项进行拖动排序的功能。这样,ItemTouchHelper 就能够监测到用户的触摸操作,并相应地处理。在上面的代码中,定义了拖动和滑动的方向,并实现了 onMove() 方法来处理拖动操作,以及 onSwiped() 方法来处理滑动操作。接下来,需要编写一个自定义的 ItemTouchHelper.Callback 类,用于处理拖动和滑动操作。注意,这里的adapter是要与需要拖动的recyclerview关联的适配器。

m0_64136170的博客 974

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

RecyclerView上下拖动条目排序,左右划出屏幕删除条目的最简单的实现

效果图参考RecyclerView的拖动和滑动 第一部分 :基本的ItemTouchHelper示例概述:ItemTouchHelperAdapter:(★)RecyclerListAdapter需要实现这个接口, RecyclerListAdapter通过ItemTouchHelperAdapter的onItemMove和onItemDismiss方法来完成条目移动、条目消除的操作,并且通过no

Android_Study_OK的博客 5252

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

上一篇: Gradle
下一篇: Java线程详解
HHcoco
博客等级 码龄13年 46粉丝 26原创
评论 24
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值