前言

续上一篇文章

这次要说的内容,正如这篇标题所述的那样………… 挑战失败,300行搞不定拖拽排序 …………

我承认严重低估了状态保存这块的处理逻辑,做各种状态保存以及读取触发,这还不是一件挺轻松的事;

逻辑这块发生了大改变,AnimatedContainer 和 GridView 也需要自定义修改一下,如果可以去掉不需要修改,但是其他部分使用,因此不得不复制过来的的系统源码部分,有600行代码的工作量;

不过这次至少把功能都实现全了;

这次先来放一下效果图,性能也没问题,应该没什么遗漏部分了:

android 移动添加拖尾效果_android

改动部分

这次对整体流程进行了调整,同时修改了AnimationContainer 和 gridView ;

整体思路是调整GridView 中 Element的顺序,并触发Item 的重构,进而触发AnimatedContainer播放动画;

而 AnimatedContainer 播放的动画是上一次的transform渐变到这次的Transfrom,而我期望的是一个由指定Transform渐变为0的动画,所以这块也要自定义处理下:

1、 提供用来存储单个Item数据的InheritedWidget

这个 InheritedWidget 的功能是存放对应 Item 在 GridView 的 子RenderObject 链表中的位置(或者可以用slot代替?),以及缓存的Item的位置信息,用来在build的时候得知需要改变的位置偏移量是多少;

android 移动添加拖尾效果_android 移动添加拖尾效果_02

在这里就没必要允许数据改变时通知监听者,毕竟仅仅当作存放共享数据的东西使用;所以 updateShouldNotify我设置为false;

2、在Element中加入修改RenderObject顺序的方法

这个方法主要分这几个步骤:

  • 1、记录当前未调整顺序时候的Item位置;用于后面再将位置信息设置回去;

android 移动添加拖尾效果_flutter_03

  • 2、调整Element中childElement中的顺序

android 移动添加拖尾效果_面试_04

  • 3、调整RenderObject中childRenderObject的顺序;

android 移动添加拖尾效果_面试题_05

由于 move 方法会调用 didAdoptChild 方法,更新调整的item的信息,最后检查renderObject链表的顺序结构是否正确,所以要在这里调整一下parentData的index顺序:

android 移动添加拖尾效果_android 移动添加拖尾效果_06

  • 4、重新设置位置信息(毕竟对于gridView来说,各个Item都是固定大小,所以index的位置信息也不会变化)

android 移动添加拖尾效果_面试题_07

3、修改AnimatedContainer

由于这次的方案是调整renderObject的顺序,所以原版AnitedContainer那种保存上一次transfrom,并渐变到当前transform的方案是不行的;

应该说,现在的AnimatedContainer的动画,应该播放的是由调整顺序前渐变到当前位置;而由于renderObject的顺序发生了改变,所以动画应该是一种由上次位置跟当前位置的该变量,渐变为0的一个动画:

这里仅仅修改 AnimatedContainerState 的 didUpdateTweens 方法即可(但这块跟自定义GridView一样,要把其他无关的东西都要复制过来,而非单单重写部分方法即可,所以其他build之类的地方可以无视,没做任何修改):

android 移动添加拖尾效果_面试_08

结语

可能有人会疑惑,已经有了之前那个德国小哥的方案,为啥我还要重新造个轮子?

关于这点,主要原因是我想利用Draggable+DragTarget的设计方案;

后续想通过自定义DragTarget的方案,实现多种复杂手势的处理;

最主要的原因还是为了尽量避免计算……

arget的设计方案;

后续想通过自定义DragTarget的方案,实现多种复杂手势的处理;

最主要的原因还是为了尽量避免计算……