一、起因
今天看到一个帖子。这个哥们使用官方的拖动列表组件 ReorderableListView
的时候,不想要默认的长按触发拖动,而是想要列表项任意内部一个组件触发拖动。结果他找了半天,去把官方源码拎了一份出来,该源码去了....
故此,这篇文章诞生了。

二、ReorderableListView 的官方例子
我们可以看到官方的代码很简单,而且不是通过长按列表项进行拖动,而是通过拖动图标进行拖动的。但是官方例子没有地方绘制拖动图标的地方,这就给人很多误解了...

然后我们找到源码的构造函数,发现其中有这么一个属性。

追踪一下这个属性就会发现正确的做法了:
官方注释的意思表达的很明确: 当:buildDefaultDragHandles
为 true的时候,将启动内置拖动操作,而这个操作在 桌面端 上是显示了一个拖动图标,但是在移动端是通过长按进行拖动操作。如果想要自定义自己的拖动方式,需要将该值设为 false,然后在你需要拖动的小组件外使用ReorderableDragStartListener
进行自定义。

这样就简单多了,我们来看一下正确做法。
三、正确操作
buildDefaultDragHandles
设置为 falseReorderableDragStartListener
包裹需要拖动的组件
dart
ReorderableListView.builder(
itemCount: list.length,
scrollDirection: Axis.vertical,
//重点 1: 关闭默认的操作
buildDefaultDragHandles: false,
itemBuilder: (context, index) {
final item = list[index];
return Card(
// 需注意:ReorderableListView构建项需要一个key作为唯一键。可以用 ValueKey.
key: ObjectKey(item),
child: Padding(
padding: const EdgeInsets.all(20),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text("内容 $index"),
// 重点 2:在需要拖动的小组件外使用这个包裹。
ReorderableDragStartListener(
index: index,
child: const Icon(Icons.drag_handle_rounded),
),
],
),
),
);
},
onReorder: (int oldIndex, int newIndex) {
logger.d("新的旧的 index: $newIndex $oldIndex");
///自己的排序方法
},
)