【Flutter】在Flutter中实现长按拖拽排序?不要太轻松,Reorderables 开源项目介绍和源码分析(作者的思路挺鬼才的,我怎么想不到)
今天是复工的第一天,现在还是不太能接受假期就这么结束了,就当是一场梦,醒了很久还是很不能接受;回正题,这篇的主题在Flutter中实现拖拽排序可以怎么做;当然,flutter 中本身就带有 ReorderableListView 这个控件,不过如果需要对 GridView、瀑布流这种来做一个拖拽排序的话,flutter本身并没有类似 ReorderableGridView 这种东西;这时候就到了万
前言
今天是复工的第一天,现在还是不太能接受假期就这么结束了,就当是一场梦,醒了很久还是很不能接受;
回正题,
这篇的主题在Flutter中实现拖拽排序可以怎么做;
当然,flutter 中本身就带有 ReorderableListView 这个控件,不过如果需要对 GridView、瀑布流这种来做一个拖拽排序的话,flutter本身并没有类似 ReorderableGridView 这种东西;
这时候就到了万能的 pub.dev 上场的时候了
reorderable 介绍
目前在pub上搜索reorder这个关键词,相关部分中,like最多的就是 [reorderable],
按照其描述,提供了多种类型的可排序组件,
其中有一个ReorderableWrap 就是我需要的效果……额,应该说一部分;也就是这次要说的内容:长按拖拽排序;
reorderable 的实现原理
还是老样子,先带着问题分析过程:
先对其实现过程提出这么几个问题:
- 长按之后会在原地留下个虚影,这个是怎么实现的;
- 移动到其他Item的时候,是怎么判断插入到目标Item的前面还是后面的?
- 排序之后,其他Item依次往后或者往前移动,这个效果是怎么实现的?
要解决这些问题,首先要看下基本机构和原理:
要了解基本机构,就要来到build方法:
build 方法快速一览:
build方法最终返回的东西,其实默认是一个Wrap,也就是那个defaultBuildItemContainer构造出来的,所以可疑的部分来到了wrappedChildren:
而这个wrappedChildren,仅仅是对child包了一层?????看来核心是这个_wrap 方法?
不过值得警觉的是,这里好像,做了个排序,先记一下:
那么来看下这个值得怀疑的_wrap方法:
_wrap 方法快速一览
_wrap 方法挺长的,不过还是先看return 部分;
_wrap 的 return 这块 ,_buildContainerForMainAxis 方法是返回一个 wrap ,对于了解结构这块,好像意义不大;
_includeMovedAdjacentChildIfNeeded 有点意思,是根据 _ghostDisplayIndex 和 _currentDisplayIndex ,以及传入的 childDisplayIndex ,对构造的 dragTarget 进行一个改造,判断是否需要添加 disappearingPreChild ,以及添加的顺序,这里先放一下,毕竟这几个参数是干啥用的,也不知道;
下面这个 dragTarget ,就是Reorderables实现的核心点了;
dragTarget 是一个stack,由三层组成:containedDraggable.builder ; 位置在left、top的一半大小的preDragTarget,以及在right、bottom,同样一半大小的nextDragTrget;
其实应该有人看出来了,不止这里,前面也多次出现过 Draggable 和 DragTarget 相关的部分的词语;
所以其实核心技术点就是Draggable跟DragTarget的组合使用;preDragTarget 跟 nextDragTarget 这两块也确实的出现了DragTarget
而上面提到的 containedDraggable.builder ,其实就是Draggable:
所以结构也很清楚了,总结一下的话就是
在Wrap的容器内有数个Item,每个Item都是一个Stack,里面除了item的内容外,还分别在两边各放一半的SizeBox来当作DragTarget;
基本结构了解完,貌似部分问题其实就有答案了……
长按留下的虚影的实现方式:
Draggable提供了 childWhenDragging 方法,以供在拖拽的时候在原地留个占位;
那么将这个占位做个半透明处理,那不就是虚影了?
Item拖拽到指定位置后,移动位置的判断方式:
正如上面在基本结构分析中所述,每个Item,其实都包含了两个DragTarget,各占一半;拖拽到哪个DragTarget,哪个DragTarget做出响应即可:
依次移动动画的实现方式:
知道了位置之后,插入的动画怎么实现,就要看这个 onWillAccept方法,它是怎么处理响应的:
首先是对一些参数进行计算,做一些边界判断,以及判断滑动响应的Item是自己本身对应的,那就不做响应,之类的东西:
下面这块就是真正去响应操作,触发动画的部分了:
在这里触发一次 setState ,修改 _nextDisplayIndex , 触发_requestAnimationToNextIndex
参数这块先不管,setState总体完成后再看看具体作用,那么看下这个_requestAnimationToNextIndex 方法:
这里的作用就是设置 _ghostDisplayIndex、_currentDisplayIndex 这两个参数的值,并触发了两个AnimationController
话说,这个_ghostDisplayIndex、_currentDisplayIndex , 是不是在哪里见过???
好像,build方法中,会根据_currentDisplayIndex 做个排序?
那么setState的作用就清楚了,直接排序,并将已经处于 childWhenDragging 状态的Item 插入过去,这样,虚影就显示到目标位置了;
而这两个AnimationController的作用,就要看其调用位置了
在前面的贴图中,可以看到,很多部分,Item的显示内容,都会包一层东西,比如说 childWhenDragging 那块,child是一个 _makeAppearingWidget ,builder方法也是,会往List中加入 _makeDisappearingWidget 构造出的widget;
总结一下的话,就是会往目标位置跟拖动Item中的Item放入_makeAppearingWidget跟_makeDisappearingWidget包裹的Item
其实这两个Controller就是控制这两个Widget的,一个负责处理添加的时候后移操作动画,一个负责处理移走的前移操作动画;
而其实现方式也简单:
没错,用SizeTranstion,通过动画改变Item大小,把后面的Item挤过去……
总结一下:
setState 后build方法将要拖拽的Item移动到目标位置,这时候Item本身的大小为0,随着动画的播放,SizeTranstion 逐渐改变Item的大小,后面的部分就这么给挤过去了……(这方法我当时确实没想到,还可以这么玩~~~)
当然会对特殊情况做个小处理:
当发生跨行的时候,让跨行的第一个Item也执行由小变大的动画;
结语
这作者的操作确实让人开眼界,我当时还以为要通过OverLay之类的东西来搞,没想到其实实现方式没必要那么复杂,这不挺简单的嘛:
国际惯例,效果图:
下面就是搞搞这个的改造,加入那个文件夹功能;
总结
要想成为架构师,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。
如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。
相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。
一、架构师筑基必备技能
1、深入理解Java泛型
2、注解深入浅出
3、并发编程
4、数据传输与序列化
5、Java虚拟机原理
6、高效IO
……
二、Android百大框架源码解析
1.Retrofit 2.0源码解析
2.Okhttp3源码解析
3.ButterKnife源码解析
4.MPAndroidChart 源码解析
5.Glide源码解析
6.Leakcanary 源码解析
7.Universal-lmage-Loader源码解析
8.EventBus 3.0源码解析
9.zxing源码分析
10.Picasso源码解析
11.LottieAndroid使用详解及源码解析
12.Fresco 源码分析——图片加载流程
三、Android性能优化实战解析
- 腾讯Bugly:对字符串匹配算法的一点理解
- 爱奇艺:安卓APP崩溃捕获方案——xCrash
- 字节跳动:深入理解Gradle框架之一:Plugin, Extension, buildSrc
- 百度APP技术:Android H5首屏优化实践
- 支付宝客户端架构解析:Android 客户端启动速度优化之「垃圾回收」
- 携程:从智行 Android 项目看组件化架构实践
- 网易新闻构建优化:如何让你的构建速度“势如闪电”?
- …
四、高级kotlin强化实战
1、Kotlin入门教程
2、Kotlin 实战避坑指南
3、项目实战《Kotlin Jetpack 实战》
-
从一个膜拜大神的 Demo 开始
-
Kotlin 写 Gradle 脚本是一种什么体验?
-
Kotlin 编程的三重境界
-
Kotlin 高阶函数
-
Kotlin 泛型
-
Kotlin 扩展
-
Kotlin 委托
-
协程“不为人知”的调试技巧
-
图解协程:suspend
五、Android高级UI开源框架进阶解密
1.SmartRefreshLayout的使用
2.Android之PullToRefresh控件源码解析
3.Android-PullToRefresh下拉刷新库基本用法
4.LoadSir-高效易用的加载反馈页管理框架
5.Android通用LoadingView加载框架详解
6.MPAndroidChart实现LineChart(折线图)
7.hellocharts-android使用指南
8.SmartTable使用指南
9.开源项目android-uitableview介绍
10.ExcelPanel 使用指南
11.Android开源项目SlidingMenu深切解析
12.MaterialDrawer使用指南
六、NDK模块开发
1、NDK 模块开发
2、JNI 模块
3、Native 开发工具
4、Linux 编程
5、底层图片处理
6、音视频开发
7、机器学习
七、Flutter技术进阶
1、Flutter跨平台开发概述
2、Windows中Flutter开发环境搭建
3、编写你的第一个Flutter APP
4、Flutter开发环境搭建和调试
5、Dart语法篇之基础语法(一)
6、Dart语法篇之集合的使用与源码解析(二)
7、Dart语法篇之集合操作符函数与源码分析(三)
…
八、微信小程序开发
1、小程序概述及入门
2、小程序UI开发
3、API操作
4、购物商场项目实战……
全套视频资料:
一、面试合集
二、源码解析合集
三、开源框架合集
欢迎大家一键三连支持,若需要文中资料,直接点击文末CSDN官方认证微信卡片免费领取【保证100%免费】↓↓↓
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)