前面咱们对于 ListView
的操做讲过 Flutter 滑动删除最佳实践,那如今咱们来了解一下 ListView
的拖拽排序。html
效果以下:api
想要达到如上效果,需使用该类,官网简介:数组
A list whose items the user can interactively reorder by dragging.app
This class is appropriate for views with a small number of children because constructing the List requires doing work for every child that could possibly be displayed in the list view instead of just those children that are actually visible.ide
All children must have a key.函数
简单翻译以下:测试
用户能够经过拖动来从新排序的列表。ui
该类适用于少许 children 的页面,由于构造列表须要为每个 children 执行操做,而不仅是可见的 children。this
全部的 children 都必须有一个 key。spa
按照惯例,查看构造函数:
ReorderableListView({
this.header,
@required this.children,
@required this.onReorder,
this.scrollDirection = Axis.vertical,
this.padding,
this.reverse = false,
}) : assert(scrollDirection != null),
assert(onReorder != null),
assert(children != null),
assert(
children.every((Widget w) => w.key != null),
'All children of this widget must have a key.',
);
复制代码
了解一下各个参数:
剩下两个就很少说了,都应该了解。
既然看完了构造函数,那咱们就能够分分钟写一个 Demo 出来:
class _ReorderableListViewPageState extends State<ReorderableListViewPage> {
List<Color> _data = [
Colors.blue,
Colors.pinkAccent,
Colors.deepPurple,
Colors.orangeAccent
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('ReorderableListViewPage'),
),
body: ReorderableListView(
header: Container(
height: 50,
),
children: _data
.map((s) => Card(
color: s,
key: Key(s.toString()),
child: Container(
width: 300,
height: 100,
),
))
.toList(),
onReorder: (int oldIndex, int newIndex) {
print("$oldIndex --- $newIndex");
}),
);
}
}
复制代码
ReorderableListView
ReorderableListView
中的 children 为用颜色定义好的 Card
onReorder
回调中打印两个参数 oldIndex
& newIndex
运行一下,看一下打印的 log:
能够看到确实是能打印出新旧两个 index, 可是这里有一个很明显的问题,
咱们你们都知道数组的下标是从 0 开始,能够看到 第一次是 从 0 到 3,第二次是从 0 到 4,
可是讲道理明明应该是 从 0 到 2,从 0 到 3。
那为何我前两次移动后的 newIndex 都 +1 了呢?
咱们这里也不去深究,
既然咱们要移动,那确定也会对源数据进行操做,否则移动也都是假的。
因此,基于这样的一个 newIndex,咱们只须要这样:
setState(() {
if(oldIndex < newIndex) {
newIndex -= 1;
}
var temp = _data.removeAt(oldIndex);
_data.insert(newIndex, temp);
});
复制代码
既然前面说到了 ListView
的删除,那这里也必须把它俩组合起来了:
其实代码很是简单,固然这也得益于 Flutter 一切皆 Widget,咱们只须要在 Card
上包裹一个 Dismissible
就ok了:
children: _data
.map((s) => Dismissible(
key: Key("dismiss $s"),
child: Card(
color: s,
key: Key(s.toString()),
child: Container(
width: 300,
height: 100,
),
),
))
.toList(),
复制代码
在 Flutter 当中,咱们能够封装不少的 Widget 来为咱们往后的开发来节省时间,
固然,也不要忘记 Flutter 当中的 Widget 测试