30

Flutter | WReorderList 一个可以指定两个item互换位置的组件

 4 years ago
source link: https://www.tuicool.com/articles/ra2QVjQ
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

最近遇到个需求,要求在一个 ListView 里面能互换两个 item 的位置,这样:

rye67rv.gif

于是,就有了现在的这个 WReorderList

WReorderList

功能就不用多说了,可以随意替换两个 item 的位置。

构造函数及其用法

还是按照老规矩,先来看一下构造函数:

WReorderList({

Key key,

@required this.children,

@required this.onIndexChanged,

this.duration = const Duration(milliseconds: 500)

}) : super(key: key);

一共四个参数:

1. key:不用多说 2. children:子组件集合 3. onIndexChanged:当两个位置变化之后的回调,要更改您自己的数据源 4. duration:动画时间

怎么用就很简单了:

WReorderList(

key: key,

children: children,

onIndexChanged: (a, b) {

setState(() {

var temp = _colors[a];

_colors[a] = _colors[b];

_colors[b] = temp;

});

},

),

组件用上了, 那如何交换位置呢?

有两种方法:

1. 给  WReorderList 设置一个 GlobalKey,然后  key.currentState.swap(0, 1) 就OK了 2. 通过  WReorderList.of(context)  方法获取到 state,然后再调用 swap 方法就好了。

WReorderList 原理解析

分析原理

首先从技术角度分析一下:

1. 怎么交换两个 item 位置? 2. 如何获取到需要交换的两个 item 的组件 3. 交换过程中两个 item 原来的位置上要被空白占用?

怎么交换两个 item 位置

这里我原本预想了好几种方案:

1. 弹出一个Overlay,在 Overlay 上做动画 2. 弹出一个 PopupRoute,用 Hero 动画 3. 染出一个 PopupRoute,在上面做动画

第一种方案被否决了,因为我 Overlay 用的不是很多。

第二种我试了一下,发现 Hero 不能用,所以也否了。

那就只剩第三种了,我试了一下用 AnimatedPositioned ,发现是可以的,那就决定是他了。

如何获取到需要交换的两个 item 的组件

这个我原本也想过用 GlobalKey,但是在列表中有一大堆的 GlobalKey 又不好,

所以我定义了一个类,该类如下:

class WReorderData {

Widget widget;

BuildContext context;

double height;


WReorderData(this.widget);

}

在用户传进来 children 以后,就用该类包住,获取到他的widget。

并且在 build 的时候用 Builder 包裹住就可以获取到当前这个 widget 的 context了。

就能获取到需要交换的两个 item 的位置。

交换过程中两个 item 原来的位置上要被空白占用?

可以看到最开始的效果中,交换过程中是被空白给占用了的,那这个高度如何获取?

我查了一下资料,发现这种是个有效的方法:

在 build 的时候加上一个 Future.delayed,100毫秒之后用当前 context 获取高度,这样就ok了。

代码如下:

Builder(builder: (context) {

Future.delayed(Duration(milliseconds: 100), () {

data[index].context = context;

data[index].height = context.size.height;

});

return swapIndex.contains(index)

? Container(height: data[index].height)

: data[index].widget;

});

总结

最近通过 PopupRoute 已经定义了两个组件了,感觉还是很有用的。

有个需要注意的点是:使用  WReorderList.of(context) 方法来获取 State 的话,一定要在子组件中,否则会找不到 state!!!

代码已上传至 GitHub:https://github.com/wanglu1209/w_reorder_list

并且发布控件到了 Pub:https://pub.dev/packages/w_reorder_list

另我个人创建了一个「Flutter 交流群」,可以添加我个人微信 「17610912320」来入群。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK