Android实现二级菜单的滑动排序

手机图片转PDF全攻略:原生与第三方工具详解 PDF作为跨平台文档标准,通过压缩算法和固定布局技术实现内容的高保真呈现。其技术原理在于将各类元素编码为PostScript语言描述的矢量图形,在移动办公场景中展现出格式统一、批注便利和传输高效三大核心价值。随着智能手机摄影能力提升,图片转PDF需求激增,2023年相关需求同比增长47%。系统原生方案如三星One UI的相册PDF导出和iOS文件应用的打印转PDF功能,能满足基础转换需求;而Adobe Scan等专业工具则提供OCR识别、智能裁剪等进阶功能。针对证件处理、商务文档等专业场景,还需配合透视校正 阅读详情

一、需求

需求很明确,我需要滑动排序二级list的数据。
可伸缩和折叠使用的是BaseExpandableListAdapter,用法大家可自行百度查看。这里我主要讲解下,我是如何实现在二级菜单中实现滑动排序的,以及在开发过程中遇到的问题,以及我自己的解决办法,希望给读者一些启示。

二、过程

解决list的滑动排序问题,我能想到的解决办法,有三种,

  • 通过RecyclerView + ItemTouchHelper;
  • 通过OnDragListener,这种方式需要自己写自定义的ViewGroup;
  • 通过ViewDragHelper。
    由于项目原因,时间比较急,所以我选择的是第一种方式。
    一开始,我的写法如下:
    @Override
    public View getChildView(int i, int i1, boolean b, View convertView, ViewGroup viewGroup) {
        if (convertView == null) {
            convertView = LayoutInflater.from(context).inflate(R.layout.device_action_list_item_child_copy, null);
        }
        RecyclerView rv = convertView.findViewById(R.id.recycler_view);
        rv.setLayoutManager(new LinearLayoutManager(context));
        Vector<String>  stringVector = childData.get(i).get(i1);

        Ap<String> ap = new Ap(context, stringVector);
        rv.setAdapter(ap);

      	ItemTouchHelperCallBack callBack = new ItemTouchHelperCallBack();
    		ItemTouchHelper helper = new ItemTouchHelper(callBack);
      
     		callBack.set(ap, stringVector);
        helper.attachToRecyclerView(rv);

        return convertView;
    }

 class ItemTouchHelperCallBack extends ItemTouchHelper.Callback{
        Ap<String> ap = null; Vector<String> datas = null;
        public void set(Ap<String> ap, Vector<String> datas) {
            this.ap = ap;
            this.datas = datas;
        }

        @Override
        public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
            int dragFrlg = 0;
            Log.e("TAG", "getMovementFlags");

            if (recyclerView.getLayoutManager() instanceof GridLayoutManager){
                dragFrlg = ItemTouchHelper.UP|ItemTouchHelper.DOWN|ItemTouchHelper.LEFT|ItemTouchHelper.RIGHT;
            }else if(recyclerView.getLayoutManager() instanceof LinearLayoutManager){
                dragFrlg = ItemTouchHelper.UP|ItemTouchHelper.DOWN;
            }
            return makeMovementFlags(dragFrlg,0);
        }

        @Override
        public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
            //滑动事件  下面注释的代码,滑动后数据和条目错乱,被舍弃
//            Collections.swap(datas,viewHolder.getAdapterPosition(),target.getAdapterPosition());
//            ap.notifyItemMoved(viewHolder.getAdapterPosition(),target.getAdapterPosition());


            //得到当拖拽的viewHolder的Position
            int fromPosition = viewHolder.getAdapterPosition();
            //拿到当前拖拽到的item的viewHolder
            int toPosition = target.getAdapterPosition();
            Log.e("TAG", "onMove fromPosition = " + fromPosition + "; toPosition = " + toPosition);
            if (fromPosition < toPosition) {
                for (int i = fromPosition; i < toPosition; i++) {
                    Collections.swap(datas, i, i + 1);
                }
            } else {
                for (int i = fromPosition; i > toPosition; i--) {
                    Collections.swap(datas, i, i - 1);
                }
            }
            ap.notifyItemMoved(fromPosition, toPosition);


            return true;
        }

        @Override
        public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
            //侧滑删除可以使用;
            Log.e("TAG", "onSwiped");

        }

        @Override
        public boolean isLongPressDragEnabled() {
            Log.e("TAG", "isLongPressDragEnabled");
            return true;
        }
        /**
         * 长按选中Item的时候开始调用
         * 长按高亮
         * @param viewHolder
         * @param actionState
         */
        @Override
        public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {

            Log.e("TAG", "onSelectedChanged actionState=" + actionState);
            if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) {
//                viewHolder.itemView.setBackgroundColor(Color.RED);
                //获取系统震动服务//震动70毫秒
                Vibrator vib = (Vibrator) context.getSystemService(Service.VIBRATOR_SERVICE);
                vib.vibrate(70);
            }
            super.onSelectedChanged(viewHolder, actionState);
        }

        /**
         * 手指松开的时候还原高亮
         * @param recyclerView
         * @param viewHolder
         */
        @Override
        public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
            super.clearView(recyclerView, viewHolder);
            Log.e("TAG", "clearView");

            viewHolder.itemView.setBackgroundColor(0);
            ap.notifyDataSetChanged();  //完成拖动后刷新适配器,这样拖动后删除就不会错乱
        }
    }

device_action_list_item_child_copy.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.RecyclerView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/recycler_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

上面代码运行之后,发现滑动没问题,但在和折叠收缩的时候,遇到了比较尴尬的问题。
问题: 折叠后,再打开,发现,无法滑动。
分析了下,我发现,每次折叠之后,再打开二级菜单,会不断的重复生成ItemTouchHelperCallBack,之后,也正是由于这个原因,导致滑动没法正常使用。
查看代码

helper.attachToRecyclerView(rv);

在ItemTouchHelper.java中发现attachToRecyclerView方法在使用之前会先比较mRecyclerView,源码如下:

    public void attachToRecyclerView(@Nullable RecyclerView recyclerView) {
        if (this.mRecyclerView != recyclerView) {
            if (this.mRecyclerView != null) {
                this.destroyCallbacks();
            }

            this.mRecyclerView = recyclerView;
            if (recyclerView != null) {
                Resources resources = recyclerView.getResources();
                this.mSwipeEscapeVelocity = resources.getDimension(dimen.item_touch_helper_swipe_escape_velocity);
                this.mMaxSwipeVelocity = resources.getDimension(dimen.item_touch_helper_swipe_escape_max_velocity);
                this.setupCallbacks();
            }

        }
    }
    
    private void destroyCallbacks() {
        this.mRecyclerView.removeItemDecoration(this);
        this.mRecyclerView.removeOnItemTouchListener(this.mOnItemTouchListener);
        this.mRecyclerView.removeOnChildAttachStateChangeListener(this);
        int recoverAnimSize = this.mRecoverAnimations.size();

        for(int i = recoverAnimSize - 1; i >= 0; --i) {
            ItemTouchHelper.RecoverAnimation recoverAnimation = (ItemTouchHelper.RecoverAnimation)this.mRecoverAnimations.get(0);
            this.mCallback.clearView(this.mRecyclerView, recoverAnimation.mViewHolder);
        }

        this.mRecoverAnimations.clear();
        this.mOverdrawChild = null;
        this.mOverdrawChildPosition = -1;
        this.releaseVelocityTracker();
        this.stopGestureDetection();
    }

当this.mRecyclerView和传参的recyclerView不相等的时候,就会不断的setupCallbacks做回调操作,就会不断的去调用自己创建的ItemTouchHelperCallBack。这也就解释了为什么,我在收缩和展开之后会出现那样的现象。
既然知道了问题,那么要如何修改呢?
所以我将RecyclerView固定,当传进去的RecyclerView一样的时候,那么attachToRecyclerView方法就不会重复的去启动ItemTouchHelperCallBack回调。
之后我做的调整如下:

    RecyclerView rv;
    Ap<String> ap;
    ItemTouchHelperCallBack callBack = new ItemTouchHelperCallBack();
    ItemTouchHelper helper = new ItemTouchHelper(callBack);

    @Override
    public View getChildView(int i, int i1, boolean b, View convertView, ViewGroup viewGroup) {
        // 尝试将这块改造成支持滑动的ListView
        if (convertView == null) {
            convertView = LayoutInflater.from(context).inflate(R.layout.device_action_list_item_child_copy, null);
            rv = convertView.findViewById(R.id.recycler_view);
            rv.setLayoutManager(new LinearLayoutManager(context));
        }

        Vector<String>  stringVector = childData.get(i).get(i1);

        ap = new Ap(context, stringVector);

        rv.setAdapter(ap);

        callBack.set(ap, stringVector);
        helper.attachToRecyclerView(rv);

        return convertView;
    }
    

修改后,测试通过,不管如何折叠收缩,滑动排序,都没有问题。

Stack Overflow导航栏重构:提升开发者体验的设计与技术实践 导航栏作为用户界面的核心组件,其设计直接影响着用户体验和操作效率。在Web开发领域,信息架构和交互设计是构建高效导航系统的关键技术。通过层级扁平化和动态优先级算法,可以显著提升用户触达核心功能的速度。以Stack Overflow为例,其导航栏重构采用了React+GraphQL技术栈,结合CSS分层渲染和智能预加载等性能优化手段,使移动端转化率提升36%,核心功能到达时间缩短56%。这种基于用户行为数据的动态导航系统,不仅适用于技术社区,也可为SaaS平台、企业级应用提供参考。热词“信息架构”和“交互设计 阅读详情

相关推荐

二级Android可展开的列表(带展开动画的expandlistview)

二级可展开列表,组条目全选checkBox,子条目有选中checkbox,不乱序

Android11 修改主菜单应用的顺序

Android11 修改主菜单应用的顺序

weixin_43824153的博客 693

列表滑动排序

是基于tableview拖动换行,排序重新继承uitableview写的带有动画的一种效果,是iOS中最常用到的上下拖动的控间

码农之重学安卓:利用androidx.preference 快速创建一、二级设置菜单(demo)

目前android上的设置菜单,大多使用preference来构建,尤其是原生的settings,此处就依葫芦画瓢,利用 androidx.preference 做一个具有一、二级菜单的demo试试!

上周的博客 1945

告别手动配置!用Vector vLinkGen 2.1.0自动生成AUTOSAR链接脚本(附bss段配置详解)

本文详细介绍了如何使用Vector vLinkGen 2.1.0工具自动生成AUTOSAR链接脚本,告别繁琐的手动配置。通过解析vLinkGen的核心架构和bss段配置实践,帮助开发者提升嵌入式软件开发效率,支持多种主流编译器,实现精确的内存分配和初始化策略。

weixin_28716181的博客 376

电信天翼云OS(ctyunos)内网离线安装Docker-CE保姆级避坑指南(附完整依赖包清单)

本文提供电信天翼云OS(ctyunos)内网环境下Docker-CE的离线安装全攻略,涵盖依赖分析、离线包制备、冲突解决等关键步骤。针对金融、政务等隔离网络场景,详细解析如何通过本地仓库构建和优化配置,实现高效安全的容器化部署,助力企业快速搭建内网Docker环境。

397

算法笔记:滑动窗口

滑动窗口作为一个考点较高的算法,广泛应用于子串问题中,本文将进行详细讲解。

愿你我都能实现自己的梦想 1114

深入解析SGLang框架:从架构设计到核心组件实现

本文深入解析了SGLang框架的架构设计与核心组件实现。SGLang是一个专为大语言模型推理设计的高效框架,其核心优势在于清晰的分层架构、高效的调度策略以及精细的内存管理。文章详细剖析了其客户端接入、服务器端调度、模型执行引擎及Tokenizer/Detokenizer管理器等关键组件,揭示了其实现高性能推理的内部机制。

coffee的博客 576

android 二级侧拉菜单,Android实现侧滑菜单栏

前言在Anroid中实现菜单栏效果通常有很多方式,有我们常见的顶部导航栏,底部导航栏,然后还有一种比较常见的就是侧滑菜单栏了。实现侧滑菜单栏也有很多种方式,那么我今天要介绍的就是Android自带的控件——DrawerLayout。用它也可以实现我们的侧滑式菜单栏,那么接下来就让我们了解下DrawerLayout的使用吧。今天涉及内容:DrawerLayout 库引用DrawerLayout 布局...

weixin_34811747的博客 1187

Weblogic安装与部署

27.免密登录,在目录Oracle\Middleware\Oracle_Home\user_projects\domains\base_domain\servers\AdminServer和Oracle\Middleware\Oracle_Home\user_projects\domains\base_domain\servers\Server-TA目录下,新建security\boot.properties文件,13.点击新建按钮,填写服务器名称,服务器监听地址,再点击下一步,最后点击完成。

m0_46259466的博客 6635

幻尔串口总线舵机控制Python SDK

幻尔串口总线舵机控制Python SDK,可以直接在PC端,不需要借助单片机对舵机进行控制。

daishabby2486的博客 4074

116.Android 简单的二级或三级列表(BaseRecyclerViewAdapterHelper)

Override//禁止滑动 布局管理器//禁止竖向滑动 RecyclerView 为垂直状态(VERTICAL)@Override//禁止横向滑动 RecyclerView 为水平状态(HORIZONTAL)}*///设置列表默认动画效果//解决数据加载不完的问题//解决数据加载完成后, 没有停留在顶部的问题// 默认提供5种方法(渐显、缩放、从下到上,从左到右、从右到左)// //一行代码开启动画。

曹二少的博客 2352

uniapp [全端兼容] - 详细实现全局修改设置字体大小功能效果,统一修改页面字号字体大小,一键改变字号整个项目立即生效,大中小字号预设、老年人大字模式场景,uniApp全平台兼容控制页面字号大小

uni-app,h5移动端网页,微信小程序,支付宝小程序,Android安卓,苹果ios,app,nvue,修改字体大小,一键调整UniApp字体大小,实时改变不用刷新,动态设置字体大小,uniapp全局修改字体字号大小,如何控制全局字号,可调整显示的字体,全项目生效,老年人大字模式,改变所有页面的字体,全局设置字体大小,实现小中大的字体切换,设置改变全局字体大小功能,如何做到全平台兼容,H5APP实现全局字体大小调整,不兼容报错,用户设置字号,全局设置应用字体大小,大中小字体修改,页面设置page-me

🏆 前端领域优质创作者 1万+

android markdown 笔记,安卓-纯纯写作 | 快速笔记 & Markdown

用户界面框架和更新体验纯纯写作用户界面框架和更新体验非常喜欢这次V14的更新,已经安装测试版体验。滑动切换markdown预览是我最喜欢的功能,可以让用户一键切换写作和阅读模式。非常顺滑,Markdown渲染直接生效,也方便用户阅读体验。建议:本次更新的重点着重在一键切换Markdown渲染,但实际解决的确是阅读和写作飞速切换功能。是否考虑将非Markdown写作的文档也加入阅读切换选择?另外,在...

weixin_28861381的博客 1122

Pixhawk2.4.8接口及引脚定义

pixhawk2.4.8接口定义图解

加斯顿工程师的博客 8741

【STM32项目】基于AI技术的多功能消防机器人(完整工程资料源码)

机器人通过巡逻扫描环境空间与障碍物、定位导航、探测物体/环境进行建模/自动地图测绘、扫描火焰、获取温湿度大小、获取空气安全情况来判断当前环境地点是否安全,检测到温度过高或检测到易燃、烟雾、有毒气体或摄像头识别到火焰时能够通过高压水泵喷射器来实现火焰隔离工作,蜂鸣器进行现场鸣笛报警,同时将当前环境温湿度大小、空气情况、环境地图、是否安全信息,将各个传感器来接收获取到的信息,实时发送到用户手机中的微信小程序,实现与用户远程监视功能,用户同时也能通过手机与电脑远程下发命令来操控机器人来实现交互功能

嵌入式技术开发 1万+

android源码-安卓源码-Android源码下载-安卓游戏源码

android源码 高仿精仿金山手机卫士应用源码V1.2 高仿精仿金山手机卫士应用源码,该应用的级别实现了金山卫士的级别功能了,可以说跟现实中我们使用的金山卫士应用的功能几乎差不 人气:9286运行环境:/android/ipad软件大小:7.40 MB更新日期:2014-01-22 android版高...

weixin_38166557的博客 166

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

android二级列表开关,Android O之通知

Android O上的通知相关更新 带有横线的选项表示有二级菜单点击横线上端的图标表示开关改功能,点击横线下面的文字表示打开二级菜单。更加紧凑直观的操作方式。应用通知权限更改 需要应用支持,对于应用发送的不同类型的通知进行管理,以净化与用户交互的方式和减少能耗。同时也支持通过后台限制应用的推送功能来延长设备续航。参考自Android O预览版上手:请给安卓厂商一个升级的理由Notification...

weixin_33027875的博客 225

Statistics and Machine Learning Toolbox

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

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

Android O之通知

Android O上的通知相关更新带有横线的选项表示有二级菜单点击横线上端的图标表示开关改功能,点击横线下面的文字表示打开二级菜单。更加紧凑直观的操作方式。应用通知权限更改 需要应用支持,对于应用发送的不同类型的通知进行管理,以净化与用户交互的方式和减少能耗。 同时也支持通过后台限制应用的推送功能来延长设备续航。 参考自Android O预览版上手:请给安卓厂商一个升级的理由Notificat

DODO~下雨不打伞 1562

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

android ui所见退所得,Android炫酷应用300例(提升篇)

第1章 常用控件001 以折叠方式实现隐藏或显示TextView002 使用可拉伸9patch图设置TextView背景003 使用TextSwitcher平滑切换多个标题004 在EditText中弹出输入电话号码的键盘005 动态创建多个自定义风格的CheckBox006 使用RadioButton创建单选按钮007 使用CheckedTextView创建单选按钮008 在ListView列表...

weixin_33266588的博客 309

Android开源项目第一篇-----个性化控件UI篇

Android开源项目第一篇——个性化控件(View)篇 本文为那些不错的Android开源项目第一篇——个性化控件(View)篇,主要介绍Android上那些不错个性化的View,包括ListView、ActionBar、Menu、ViewPager、Gallery、GridView、ImageView、ProgressBar及其他如Dialog、Toast、EditText、

Tom_xiaoxie的博客 962

【微软周报】第四期

该控件支持将同类操作整合为“主按钮+二级菜单”的结构,例如针对图片文件,原本分散的“打开”“编辑”“设为桌面背景”等操作,未来将统一整合为“用照片应用打开”主选项,画图、截图工具等关联程序则收纳在主选项旁的浮出菜单中。目前,“分离式右键菜单”仍处于早期开发阶段,尚未在任何Windows 11 Insider预览版中开放用户测试,但微软已在官方GitHub仓库公布相关API,邀请开发者提前适配实验该功能支持将同类操作整合为“主按钮+二级菜单”的结构,目前仍处于早期开发阶段。

2502_93021708的博客 1325

电脑与手机特殊符号高效输入全攻略

特殊符号输入是数字办公中的常见需求,其核心原理是通过Unicode编码或系统快捷键实现快速调用。在技术实现上,Windows系统通过Alt+数字小键盘组合键,Mac系统利用Option键组合,都能高效输入版权符号、数学符号等专业字符。对于移动端,安卓和iOS输入法通过长按触发符号变体,结合文本替换功能大幅提升输入效率。在工程实践中,程序员可通过VSCode插件快速插入编程符号,学术工作者则依赖LaTeX或Word的Alt+X转换功能。随着网络热词发展,颜文字和组合符号的创意使用也成为新的技术应用场景。掌握这

weixin_29172201的博客 398

AutoGLM-Phone输入法切换失败?ADB Keyboard安装详解

本文介绍了如何在星图GPU平台上自动化部署Open-AutoGLM – 智谱开源的手机端AI Agent框架镜像,实现AI驱动的手机自动化操作。通过平台一键部署后,该框架可基于屏幕理解与ADB指令,完成如‘打开小红书搜索川菜探店’等典型任务,适用于移动场景下的智能交互与远程数字助理应用。

weixin_36064575的博客 439

告别手动点击!Open-AutoGLM让手机自己操作

本文介绍了如何在星图GPU平台上自动化部署Open-AutoGLM – 智谱开源的手机端AI Agent框架镜像,实现自然语言驱动的安卓手机自动化操作。用户只需输入中文指令(如‘打开淘宝搜索机械键盘并加入购物车’),系统即可完成界面识别、动作规划与ADB执行,典型应用于跨App任务协同与数字生活助理场景。

weixin_29476595的博客 338

androidstudio按钮距离屏幕_特斯拉的中控大屏真的比实体按钮效率更高吗?

对于那些近几年才学会开车的人来说,驾驶更为智能的汽车(比如:Tesla 特斯拉)是一种完全不同的体验。新车配备了后视摄像头,停车辅助系统,车道变换辅助系统,自适应巡航控制系统等等。所有这些功能应该使驾驶更安全,更舒适。事实上,果然如此吗?正文:特斯拉 Model S 有几个实体按钮 - 全部放在方向盘上或非常靠近方向盘。比如巡航控制,雨刷和灯光都可以通过这些来控制。但大多数“二级”功能(像后视摄像...

weixin_36393674的博客 227
上一篇: null is not an object (evaluating ‘this._sceneRefs[t].setNativeProps‘), stack:
下一篇: 我是如何阅读ARouter源码的
程序猿的玻璃心
博客等级 码龄14年 181粉丝 168原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值