Flutter ListView 拖拽排序了解一下

前面咱们对于 ListView 的操做讲过 Flutter 滑动删除最佳实践,那如今咱们来了解一下 ListView 的拖拽排序。html

效果以下:api

ReorderableListView

想要达到如上效果,需使用该类,官网简介:数组

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.',
);
复制代码

了解一下各个参数:

  • header:是一个不参与拖动排序的 Widget
  • children:不用多说,列表项
  • onReorder:见名知意,从新排序后的回调
  • scrollDirection:方向

剩下两个就很少说了,都应该了解。

简单使用

既然看完了构造函数,那咱们就能够分分钟写一个 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");
          }),
    );
  }
}
复制代码
  1. 首先咱们定义好一组颜色的列表
  2. 而后在 build 方法中返回 ReorderableListView
  3. ReorderableListView 中的 children 为用颜色定义好的 Card
  4. 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);
});
复制代码
  1. 先判断是向上仍是向下拖拽
  2. 若是是向下拖拽,那么 newIndex 会多加一个,咱们把它减掉
  3. 而后咱们删除旧数据并保存它
  4. 最后在新的 index 上插入

ListView 的拖拽排序和删除

既然前面说到了 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 测试

相关文章
相关标签/搜索