美文网首页Flutter
Flutter 之 DataTable (六十一)

Flutter 之 DataTable (六十一)

作者: maskerII | 来源:发表于2022-05-10 21:54 被阅读0次

DataTable 是 flutter 提供的一个表格控件

1. DataTable

属性介绍

DataTable 属性 介绍
columns @required 列数组 <DataColumn>
sortColumnIndex 有排列箭头的列,仅仅是展示箭头
sortAscending 是否升序,默认为 true, 排列顺序,仅仅是箭头向上还是向下
onSelectAll 左上角全选按钮点击回调
dataRowHeight Rows 中每条 Row 高度,默认为 kMinInteractiveDimension = 48.0
headingRowHeight 顶部 Row 高度,默认为 56.0
horizontalMargin 左侧边距,默认为 24.0
columnSpacing 每一列间距,默认为 56.0
showCheckboxColumn 是否展示左侧 checkbox 这一列,默认为 true
dividerThickness 分割线宽度,默认为 1.0
rows @required 行数组 <DataRow>
DataColumn 属性 介绍
label 文本
tooltip 长按提示
numeric 是否居右,默认为 false
onSort 点击排序箭头回调函数
DataRow 属性 介绍
selected checkbox 是否选中,默认为 false
onSelectChanged 左侧 checkbox 点击事件
color DataRow 颜色回调函数
cells <DataCell> 数组
DataCell 属性 介绍
child 子控件
placeholder 是否为 placeholder,会改变 Text 样式
showEditIcon 是否展示编辑按钮
onTap 点击事件

2. 基本使用


class MSDataTableDemo extends StatefulWidget {
  const MSDataTableDemo({Key? key}) : super(key: key);

  @override
  State<MSDataTableDemo> createState() => _MSDataTableDemoState();
}

class _MSDataTableDemoState extends State<MSDataTableDemo> {
  List<MSDataRowModel> _datas = [];
  @override
  void initState() {
    _datas.add(MSDataRowModel("劫", "刺客", "20", "2800"));
    _datas.add(MSDataRowModel("烬", "射手", "30", "3200"));
    _datas.add(MSDataRowModel("提莫", "法师", "23", "2500"));
    _datas.add(MSDataRowModel("洛克", "战士", "30", "3550"));
    _datas.add(MSDataRowModel("拉克丝", "法师", "18", "2000"));
    _datas.add(MSDataRowModel("武器大师", "战士", "19", "1800"));
    _datas.add(MSDataRowModel("慎", "坦克", "25", "2600"));
    _datas.add(MSDataRowModel("盖伦", "战士", "25", "2800"));
    _datas.add(MSDataRowModel("皇子", "战士", "25", "2600"));
    _datas.add(MSDataRowModel("盲僧", "刺客", "25", "2800"));
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("DataTableDemo")),
      body: SingleChildScrollView(
        scrollDirection: Axis.vertical,
        child: SingleChildScrollView(
          scrollDirection: Axis.horizontal,
          child: _dataTable(),
        ),
      ),
    );
  }

  _dataTable() {
    return DataTable(
      columns: _dataColumnList(),
      rows: _dataRowList(),
      dataRowHeight: 60, // Rows 中每条 Row 高度
      headingRowHeight: 100, // 顶部 Row 高度
      horizontalMargin: 20, // 左侧边距
      columnSpacing: 80, // 每一列间距
      showCheckboxColumn:
          true, // 是否展示左侧 checkbox,默认为 true,需要和 DataRow 的onSelectChanged 一起使用
      dividerThickness: 2, // 分割线宽度
      // 左上角全选按钮点击回调 如果实现此函数,需要手动实现全选功能
      // onSelectAll: (boolValue) {
      //   print("DataTable onSelectAll");
      // },
    );
  }

  List<DataColumn> _dataColumnList() {
    List<DataColumn> columns = [];
    columns.add(DataColumn(label: Text("名字")));
    columns.add(DataColumn(label: Text("类型")));
    columns.add(DataColumn(label: Text("等级")));
    columns.add(DataColumn(
      label: Text("战力"),
      tooltip: "英雄战斗力", // 长按提示
      numeric: false, // 是否居右,默认为 false
    ));
    return columns;
  }

  List<DataRow> _dataRowList() {
    List<DataRow> rows = [];
    _datas.forEach((element) {
      rows.add(DataRow(
        cells: [
          DataCell(Text(element.name)),
          DataCell(Text(element.type)),
          DataCell(Text(element.level)),
          DataCell(
            Text(element.fightingCapacity),
            // 点击事件
            onTap: () {
              print("DataCell.onTap");
            },
            placeholder:
                true, // 是否是 placeholder,默认为 false,设置为 true 时 Text 会变成灰色 placeholder
            showEditIcon: true, //是否展示编辑图标
          ),
        ],
        onSelectChanged: (select) {
          element.onSelected = select!;
          setState(() {});
        },
        selected: element.onSelected, // 左侧 checkbox 是否选中
        color: MaterialStateProperty.resolveWith((states) {
          if (states.contains(MaterialState.selected)) {
            return Colors.amber;
          } else {
            return Colors.grey[100];
          }
        }),
      ));
    });
    return rows;
  }
}

class MSDataRowModel {
  String name;
  String fightingCapacity;
  String type;
  String level;
  bool onSelected = false;
  MSDataRowModel(this.name, this.type, this.level, this.fightingCapacity);
}

88.gif

3. 排序

在 DataTable 提供的属性中,仅仅是一个箭头展示效果和点击事件而已,如果需要点击切换排序,还需要自定义代码来排序,然后刷新页面才可以。

  return DataTable(
    ...
    sortColumnIndex: 3, // 有排列箭头的列,仅仅是展示箭头 需和对应的DataColumn中的onSort 一起使用
    sortAscending: _sortAscending, // 排列顺序,仅仅是箭头向上还是向下
    ...
  );
List<DataColumn> _dataColumnList() {
  List<DataColumn> columns = [];
  ...
  columns.add(DataColumn(
    ...
    onSort: (columnIndex, ascending) {
      print("index = $columnIndex, booValue = $ascending");

      _sortAscending = ascending;
      _sortDatas();
      setState(() {});
    },
  ));
  return columns;
}

  _sortDatas() {
    if (_sortAscending) {
      _datas.sort((a, b) {
        return int.parse(a.fightingCapacity)
            .compareTo(int.parse(b.fightingCapacity));
      });
    } else {
      _datas.sort((a, b) {
        return int.parse(b.fightingCapacity)
            .compareTo(int.parse(a.fightingCapacity));
      });
    }
  }

完整代码


class MSDataTableDemo extends StatefulWidget {
  const MSDataTableDemo({Key? key}) : super(key: key);

  @override
  State<MSDataTableDemo> createState() => _MSDataTableDemoState();
}

class _MSDataTableDemoState extends State<MSDataTableDemo> {
  List<MSDataRowModel> _datas = [];
  bool _sortAscending = true;
  @override
  void initState() {
    _datas.add(MSDataRowModel("劫", "刺客", "20", "2800"));
    _datas.add(MSDataRowModel("烬", "射手", "30", "3200"));
    _datas.add(MSDataRowModel("提莫", "法师", "23", "2500"));
    _datas.add(MSDataRowModel("洛克", "战士", "30", "3550"));
    _datas.add(MSDataRowModel("拉克丝", "法师", "18", "2000"));
    _datas.add(MSDataRowModel("武器大师", "战士", "19", "1800"));
    _datas.add(MSDataRowModel("慎", "坦克", "25", "2600"));
    _datas.add(MSDataRowModel("盖伦", "战士", "25", "2800"));
    _datas.add(MSDataRowModel("皇子", "战士", "25", "2600"));
    _datas.add(MSDataRowModel("盲僧", "刺客", "25", "2800"));
    _sortDatas();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("DataTableDemo")),
      body: SingleChildScrollView(
        scrollDirection: Axis.vertical,
        child: SingleChildScrollView(
          scrollDirection: Axis.horizontal,
          child: _dataTable(),
        ),
      ),
    );
  }

  _dataTable() {
    return DataTable(
      columns: _dataColumnList(),
      rows: _dataRowList(),
      dataRowHeight: 60, // Rows 中每条 Row 高度
      headingRowHeight: 100, // 顶部 Row 高度
      horizontalMargin: 20, // 左侧边距
      columnSpacing: 80, // 每一列间距
      showCheckboxColumn:
          true, // 是否展示左侧 checkbox,默认为 true,需要和 DataRow 的onSelectChanged 一起使用
      dividerThickness: 2, // 分割线宽度
      sortColumnIndex: 3, // 有排列箭头的列,仅仅是展示箭头 需和对应的DataColumn中的onSort 一起使用
      sortAscending: _sortAscending, // 排列顺序,仅仅是箭头向上还是向下
      // 左上角全选按钮点击回调 如果实现此函数,需要手动实现全选功能
      // onSelectAll: (boolValue) {
      //   print("DataTable onSelectAll");
      // },
    );
  }

  List<DataColumn> _dataColumnList() {
    List<DataColumn> columns = [];
    columns.add(DataColumn(label: Text("名字")));
    columns.add(DataColumn(label: Text("类型")));
    columns.add(DataColumn(label: Text("等级")));
    columns.add(DataColumn(
      label: Text("战力"),
      tooltip: "英雄战斗力", // 长按提示
      numeric: false, // 是否居右,默认为 false
      onSort: (columnIndex, ascending) {
        print("index = $columnIndex, booValue = $ascending");

        _sortAscending = ascending;
        _sortDatas();
        setState(() {});
      },
    ));
    return columns;
  }

  List<DataRow> _dataRowList() {
    List<DataRow> rows = [];
    _datas.forEach((element) {
      rows.add(DataRow(
        cells: [
          DataCell(Text(element.name)),
          DataCell(Text(element.type)),
          DataCell(Text(element.level)),
          DataCell(
            Text(element.fightingCapacity),
            // 点击事件
            onTap: () {
              print("DataCell.onTap");
            },
            placeholder:
                true, // 是否是 placeholder,默认为 false,设置为 true 时 Text 会变成灰色 placeholder
            showEditIcon: true, //是否展示编辑图标
          ),
        ],
        onSelectChanged: (select) {
          element.onSelected = select!;
          setState(() {});
        },
        selected: element.onSelected, // 左侧 checkbox 是否选中
        color: MaterialStateProperty.resolveWith((states) {
          if (states.contains(MaterialState.selected)) {
            return Colors.amber;
          } else {
            return Colors.grey[100];
          }
        }),
      ));
    });
    return rows;
  }

  _sortDatas() {
    if (_sortAscending) {
      _datas.sort((a, b) {
        return int.parse(a.fightingCapacity)
            .compareTo(int.parse(b.fightingCapacity));
      });
    } else {
      _datas.sort((a, b) {
        return int.parse(b.fightingCapacity)
            .compareTo(int.parse(a.fightingCapacity));
      });
    }
  }
}

class MSDataRowModel {
  String name;
  String fightingCapacity;
  String type;
  String level;
  bool onSelected = false;
  MSDataRowModel(this.name, this.type, this.level, this.fightingCapacity);
}

87.gif

注意 我们的 fightingCapacity 用的是 String 类型,如果不转换直接比较,排序会出现问题。

参考:https://www.jianshu.com/p/6615df8941f3

相关文章

网友评论

    本文标题:Flutter 之 DataTable (六十一)

    本文链接:https://www.haomeiwen.com/subject/xxsrurtx.html