Flutter进阶技巧之300行代码实现拖拽排序

Posted 学习Android的第1024天

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flutter进阶技巧之300行代码实现拖拽排序相关的知识,希望对你有一定的参考价值。

前言

有没有不计算,代码少的方式来实现这个拖拽排序呢?

文末有福利!!!

效果设计

拖拽排序这块,其实最复杂的部分就是排序动画的处理,在 reOrderables 中,可以说绝大部份代码都是为了定位排序位置,最后通过调整Size,用AnimationController辅助处理,这种方式来实现一个折叠动画;

说实话,效果是有了,但是这代码确实让人看的容易晕;

android 中,其实更多的排序动画是类似这种平移动画的:

所以这次我也计划使用这种动画实现(其实就是懒);

当然,该有的虚影之类的也是应该有的东西;

实现方案:

获取各个Item的位置信息

要想实现上面的平移动画,第一步就是知道各个Item自己本身在GridView中的位置坐标;

关于获取位置的实现方式,大部分方案都是通过给各个Item加上GlobalKey,然后获取renderObject来测量;

不过这次玩点花的,我想尽量少些代码的同时,减少GlobalKey的数量;

众所周知,sliver在layout方法结束后,会调用 didFinishLayout 方法,来通知layout结束,并公布当前缓存的第一个和最后一个Item的index;

既然这样,我在layout方法结束的时候,获取一下各个Item所在的起始位置不就行了?

提供一个共享Item位置的 InheritedWidget

这个InheritedWidget的作用,就是保存两个列表,分别存放Item的实际位置和重排序位置:

至于这两个List干啥用的,后面再揭秘;

PS : 其实用List存放位置信息是不合适的,因为List中的第一个Item,并不一定是GridView中index = 0 的那个Item,所以最后处理的时候要做一个index的转换,比较麻烦;

我这里偷懒,先用List存了

给我一个Key,还你一片Offset

继承GridView,重写buildChildLayout , 给SliverGrid设置一个GlobalKey:

这个 Key 的作用,就是获取 SliverGrid 的 Element;而通过 Element 就可以拿到 各个child 对应的Element;

不过这里稍微不同的是,由于所说方法名是didFinishLayout,但是实际上,这里是performLayout方法的最后一步而已,所以performLayout方法实际上是没有完成的;

因此parent默认是不允许访问child的size的,如果调用renderOject.localToGlobal就会报错;

既然这样,可以用另一种方式获取child的位置信息,比如说,ParentData:

PS :其实Key这玩意也可以不用设置,在前面对Sliver的分析中已经知道了,调用 SliverChildDelegate 的 didFinishLayout方法的就是 SliverGrid 的 Element ,说白了,如果勤奋点,把 sliver那块重写下,就可以把Element传过来了;

同时因为 Element 可以视为 BuildContext , context 也能拿到,进而也能用来获取InheritedWidget,共享数据也很方便,当然这里是放到build方法中获取InheitedWidget来偷懒;

所以我感觉最合适的方法是重写sliver以及这个SliverChildDelegate……

懒人福音 AnimatedContainer

在这里对build的Item进行一定的处理,首先最外层包一层AnimatedContainer:

AnimatedContainer 可以说是一个全自动动画播放器,没有AnimationController和Tween,仅仅一个setState就可以方便的实现切换动画;

而前面存放的两个List中的内容,就在这里用上了:

只需要把两个Item的Offset一减,setState之后就能实现位置平移动画;

PS:这个方案来自一位德国小哥的项目

不过我感觉他也写的挺麻烦的,没有结合DragTarget,而是仅仅通过Draggable返回的手势信息来做的碰撞检测,看的有点眼花……😵‍💫

PPS : 我知道他为什么不用DragTarget了……GridView本身的hitTest,是根据主轴交叉轴信息修改了点击坐标位置的,但是AnimatedContainer 中加入Transform后,这个坐标再次经过修改后,就根本命中不了任何一个Item…………所以,当Item通过Transform改变位置后,Draggable和DragTarget 是不会响应任何手势的……

至于这两个List中的内容是如何改变的,就是下面这部分了:

Pull My “Draggable” Trigger !

这里就来到了熟悉的Draggable+DragTarget部分:

在上图中,最后构造出的Item是一个Stack,其中原本 Item 应有的 child 传递给了buildDraggable方法构造Draggable;

另一部分就是DragTarget ,关键部分就在这里,其所做的事其实就是检测到碰撞后,根据自己和碰撞Item的index,重排序一下:

最后通过回调,触发外面的setState,启动动画即可:

结语:

两个文件共计不到300行:

虽说不到300行实现了目标效果,不过bug还是有的,比如说再次滑动切换DragTarget的时候,位置信息就算错了,估计某个状态没存上,onDragEnd之后通知保存数据这块也没做处理

但是300行确实能实现核心逻辑,剩下的东西都是些边边角角的部分,多也多不到哪去……吧,大概吧~~~~~

回正题:国际惯例,看下效果:

更新:

后来看了下,这块还真没法用Draggable+DragTarget 的方案,还真只能靠Draggale返回的手势回调来做计算…………

原因就是AnimatedContainer 这块中的PPS补充部分……

不计算这个目标流产了……

通过计算的方式估计要加个200行代码……

或者说有什么方案能让GridView的Item移动,但DragTarget不移动呢………… 比如说用Stack往Grid上面覆盖一层,用来放DragTarget呢 …………

部分……

不计算这个目标流产了……

通过计算的方式估计要加个200行代码……

或者说有什么方案能让GridView的Item移动,但DragTarget不移动呢………… 比如说用Stack往Grid上面覆盖一层,用来放DragTarget呢 …………

最后

按照国际惯例,给大家分享一套十分好用的Android进阶资料:《全网最全Android开发笔记》。

整个笔记一共8大模块、729个知识点,3382页,66万字,可以说覆盖了当下Android开发最前沿的技术点,和阿里、腾讯、字节等等大厂面试看重的技术。

好啦,这份资料就给大家介绍到这了,有需要详细文档的小伙伴,可以微信扫下方二维码回复JJ免费领取哈~

因为所包含的内容足够多,所以,这份笔记不仅仅可以用来当学习资料,还可以当工具书用。

如果你需要了解某个知识点,不管是Shift+F 搜索,还是按目录进行检索,都能用最快的速度找到你要的内容。

相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照整个知识体系编排的。

(一)架构师必备Java基础

1、深入理解Java泛型

2、注解深入浅出

3、并发编程

4、数据传输与序列化

5、Java虚拟机原理

6、高效IO

……

(二)设计思想解读开源框架

1、热修复设计

2、插件化框架设计

3、组件化框架设计

4、图片加载框架

5、网络访问框架设计

6、RXJava响应式编程框架设计

……

(三)360°全方位性能优化

1、设计思想与代码质量优化

2、程序性能优化

  • 启动速度与执行效率优化
  • 布局检测与优化
  • 内存优化
  • 耗电优化
  • 网络传输与数据储存优化
  • APK大小优化

3、开发效率优化

  • 分布式版本控制系统Git
  • 自动化构建系统Gradle

……

(四)Android框架体系架构

1、高级UI晋升

2、Android内核组件

3、大型项目必备IPC

4、数据持久与序列化

5、Framework内核解析

……

(五)NDK模块开发

1、NDK开发之C/C++入门

2、JNI模块开发

3、Linux编程

4、底层图片处理

5、音视频开发

6、机器学习

……

(六)Flutter学习进阶

1、Flutter跨平台开发概述

2、Windows中Flutter开发环境搭建

3、编写你的第一个Flutter APP

4、Flutter Dart语言系统入门

……

(七)微信小程序开发

1、小程序概述及入门

2、小程序UI开发

3、API操作

4、购物商场项目实战

……

(八)kotlin从入门到精通

1、准备开始

2、基础

3、类和对象

4、函数和lambda表达式

5、其他

……

好啦,这份资料就给大家介绍到这了,有需要详细文档的小伙伴,可以微信扫下方二维码回复JJ免费领取哈~

创作挑战赛 新人创作奖励来咯,坚持创作打卡瓜分现金大奖

以上是关于Flutter进阶技巧之300行代码实现拖拽排序的主要内容,如果未能解决你的问题,请参考以下文章

flutter实现文字识别之图片拖拽选框选取截取文字

Android安卓进阶技巧之全局自定义字体的实现

帆软怎么实现报表的排序,隐藏,拖拽

Flutter 拖拽排序组件 ReorderableListView

[DevExpress]GridControl拖拽行记录排序

[DevExpress]GridControl拖拽行记录排序