Home Flutter DataTable 无法居中的BUG以及优化
Post
Cancel

Flutter DataTable 无法居中的BUG以及优化

Flutter DataTable的bug

在使用原生控件DataTable时,会发现表内单元格的内容无法居中,单元格右侧会多出一段。这实际是DataTable的一个bug, DataTable的部分源码:

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
41
42
43
44
45
46
47
48
49
50
class DataTable extends Stateless {
    
    //...
        
    Widget build(BuildContext context) {
      	//...
        tableRows[0].children[displayColumnIndex] = _buildHeadingCell(
            context: context,
            padding: padding,
            label: column.label,
            tooltip: column.tooltip,
            numeric: column.numeric,
            //1.这里的onSort一定是不等于null的
            onSort: () => column.onSort != null ? column.onSort(dataColumnIndex, sortColumnIndex != dataColumnIndex || !sortAscending) : null,
            sorted: dataColumnIndex == sortColumnIndex,
            ascending: sortAscending,
          );
    }
    
    //...
    
    Widget _buildHeadingCell({
        BuildContext context,
        EdgeInsetsGeometry padding,
        Widget label,
        String tooltip,
        bool numeric,
        VoidCallback onSort,
        bool sorted,
        bool ascending,
      }) {
        //2.导致这个if判断是一定会执行的
        if (onSort != null) {
          //arrow的宽度是16
          final Widget arrow = _SortArrow(
            visible: sorted,
            down: sorted ? ascending : null,
            duration: _sortArrowAnimationDuration,
          );
          //arrowPadding的宽度是2
          const Widget arrowPadding = SizedBox(width: _sortArrowPadding);
          //这样,会导致单元格的后面,多出18的长度
          label = Row(
            textDirection: numeric ? TextDirection.rtl : null,
            children: <Widget>[ label, arrowPadding, arrow ],
          );
        }
        //...
    }
}

所以,需要将上面注释1的代码,改成下面这样就可以了:

1
onSort: column.onSort != null ? () => column.onSort(dataColumnIndex, sortColumnIndex != dataColumnIndex || !sortAscending) : null,

升级DataTable

原生DataTable其实不是很好用,单元格无法对齐,无法设置背景颜色,没有网格线等等。

通过封装的EnhanceDataTable支持设置背景颜色、单元格自动居中、支持网格线、首行首列固定的优点。

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
41
42
43
44
45
46
47
48
49
50
51
52
import 'package:flutter/material.dart'
    hide DataTable, DataColumn, DataRow, DataCell;

import 'data_table.dart';

class EnhanceDataTable<T> extends StatefulWidget {
  //是否固定第一行
  final bool fixedFirstRow;
  //是否固定第一列
  final bool fixedFirstCol;
  //包括header以及cell内容的list
  final List<List<T>> rowsCells;
  //支持自定义单元格格式
  final Widget Function(T data) cellBuilder;
  //单元格高度
  final double cellHeight;
  //单元格两边空白cellSpacing/2
  final double cellSpacing;
  //设置不同列的宽度
  final double Function(int columnIndex) columnWidth;
  //表格头的背景颜色
  final Color headerColor;
  final TextStyle headerTextStyle;
  //表格内容的颜色交替
  final List<Color> cellAlternateColor;
  //表格内容的字体颜色
  final TextStyle cellTextStyle;
  //是否显示网格线
  final bool showBorderLine;
  //网格线颜色
  final Color borderColor;

  EnhanceDataTable({
    this.fixedFirstRow = false,
    this.fixedFirstCol = false,
    @required this.rowsCells,
    @required this.columnWidth,
    this.cellBuilder,
    this.cellHeight = 56.0,
    this.cellSpacing = 10.0,
    this.headerColor,
    this.cellAlternateColor,
    this.headerTextStyle,
    this.cellTextStyle,
    this.showBorderLine = true,
    this.borderColor,
  })  : assert(cellAlternateColor == null || cellAlternateColor.length == 2),
        assert(borderColor == null || showBorderLine);

  @override
  State<StatefulWidget> createState() => EnhanceDataTableState();
}

注意到一开始的import:

1
2
3
import 'package:flutter/material.dart'
    hide DataTable, DataColumn, DataRow, DataCell;
import 'data_table.dart';

首先,是移除掉原生DataTable相关控件,然后,使用我们自己的data_table.dart文件。这个是将源码文件data_table.dart拷贝到本地,并修复了上面说的bug。

源码:EnhanceDataTable

This post is licensed under CC BY 4.0 by the author.