Flutter

前言

最近由于公司变动业务变动,我开始进行 flutter 业务开发。flutter 是最近两年新起的技术,最重要的功能是跨端开发,能够整合 Android 和 iOS,一端两用,最近连 web 也开始支持编译了。由于之前的业务都是通过 iOS 和 Android 开发的,目前我们公司的 flutter 内容也都是通过插件的方式放在 iOS 和 Android 里面,最近就开始处理一个业务,能够拖动列表进行内容排序,使用了 ReorderableListView 这个 Widget,下面我介绍一下这个 Widget 的使用及我使用此组件遇到的问题。

使用

先简单介绍一下 ReorderableListView 类的属性,官方介绍点这里

Constructors

ReorderableListView({Widget header, @required List children, @required ReorderCallback onReorder, Axis scrollDirection: Axis.vertical, EdgeInsets padding, bool reverse: false })

属性

  • children -> List: 用于插入一些能够拖动 Widget 列表内容
  • header -> Widget: 用于定义列表项头部的部分,主要用来提示列表项的内容
  • onReorder -> ReorderCallback(oldIndex,newIndex): 当列表被拖动时执行的回调,有两个参数一个 oldIndex 表示拖动的 Widget 开始的位置,newIndex 表示拖动模块新的位置
  • padding->EdgeInsets: 设置内边距
  • scrollDirection->Axis:设置列表滚动的轴
  • reverse ->bool: 设置滚动列表是否沿读取方向滚动
  • key->Key

示例

由于公司项目已经做了内容,我也懒得自己写例子了,使用公司项目中的列表,手写简化出来做示例,代码稍微修改下即可运行。

List list;//展示的列表,应该定义在类里面,这里只是
@override
void initState(){
初始化
  list=[];
  for(var i=0;i<10;i++){
      list.add(i);
  }
}
@override
Widget build() {

  reutrn ReorderableListView(
    header: Container(
      alignment: Alignment(-0.9, 0),
      height: 45,
      padding: EdgeInsets.only(top: 15),
      child: Text('例子'),
    ),
   children: list.map((item) {
      return Container(
          key: Key(item.toString()),
          height: 45,
          width: double.infinity,
          margin: EdgeInsets.only(top: 5),
          color: Colors.white,
          child: Text(item.toString()));
    }).toList(),
    onReorder: (int oldIndex, int newIndex) {
      setState(() {
        //交换数据
        if (newIndex > oldIndex) {
          newIndex -= 1;
        }
        final int item = list.removeAt(oldIndex);
        list.insert(newIndex, item);
      });
    },
    );
  }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

写出来大概的效果如下:

效果图

使用起来非常简单,部分属性都有初始化,只需要简单定义 children 和 onReorder 属性即可完成最简单的拖动列表。

解决拖动上滑出现大量空白问题

问题重现:

滑动问题

此问题只有在特定的情况下出现,我的出现情况是在设置了此 Widget 外套用了 ConstrainedBox 设置来设置其高度,而我把这个问题拿来写是因为我查询了几天资料都没有找到问题的解决方案,在 flutter issue 中也没有找到真正的解决方式,所以写出来希望能帮到正好遇到此问题的朋友。

要解决这个问题,我们就需要从 ReorderableListView 这个类下手了,ReorderableListView 类本质也是一个通过其它封装的 Widget 一起重组的一个组件,就像我们自己写的一个组件一样,如果业务需要,我们要不就只有自己去封装,要不就只有找到原组件问题,去改造成适应自己的业务。如果说改源码会有顾虑,你可以把这个当做自己为了适应需求而写的组件。

查看 reorderable_list.dart 文件第 184 行:

 // This value is used when the extents haven't yet been calculated from
 // the currently dragging widget, such as when it first builds.
 static const double _defaultDropAreaExtent = 100.0;
1
2
3

修改为

static const double _defaultDropAreaExtent = 5.0;
1

设置成 5 是因为还需要留一点空隙去让最后一个元素能够拖动,不然最后其它元素都不能拖动到最后一个元素后面。

然后再修改第 368 行

// Drops toWrap into the last position it was hovering over.
    void onDragEnded() {
+      reorder(_dragStartIndex, _currentIndex);
+      _scrollController.animateTo(
+        0,
+        duration: _scrollAnimationDuration,
+        curve: Curves.easeInOut,
+      );
    }

1
2
3
4
5
6
7
8
9
10

目的是为了让每次拖动完成后能回到最初始的位置。好了,大致修改完成。

如果你们有正好遇到此问题的朋友还有更好的解决方案,希望告知。

Last Updated: 8/12/2020, 1:34:59 PM