Flutter表格布局插件flexible_table的使用

Flutter表格布局插件flexible_table的使用

在本教程中,我们将介绍如何使用Flutter中的flexible_table插件来创建一个具有灵活列宽、固定表头且支持过滤和排序功能的表格。该插件还支持处理非常大的数据集,并提供了多种自定义选项。


引言

FlexTableflexible_table 插件的核心类,它允许用户创建一个具有以下特性的表格:

  • 可调整列宽:所有列都可以自由调整宽度。
  • 固定表头:表头始终可见。
  • 内置过滤和排序功能:支持对列进行过滤和排序操作。
  • 高性能:能够处理非常大的数据集(如56k或190k行),无需分页即可流畅展示。

此外,该插件利用了 multi_split_view 包来实现列的灵活调整,并使用 popover 包来增强过滤功能的性能。


组件

FlexTable

FlexTable 是整个插件的核心类,负责管理表格的所有行为。以下是创建一个基本 FlexTable 的示例代码:

class MyWidget extends StatefulWidget {
  MyWidget({required this.headers, super.key});
  final List<String> headers;

  [@override](/user/override)
  State createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
  final FlexTableController _controller = FlexTableController();
  late final StreamSubscription _columnSubscription;

  [@override](/user/override)
  void initState() {
    super.initState();

    _columnSubscription = _controller.columnStream.listen((_) {
      final sizes = _controller.columnSizes.map((s) => s.flex).toList();
      print('Updated column flex values: $sizes');
    });
  }

  [@override](/user/override)
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('My Widget')),
      body: FlexTable(
        controller: _controller,
        dataBuilder: const FlexStripeCellBuilder(), // 使用默认的数据单元格渲染器
        headers: widget.headers,
      ),
    );
  }
}

解释:

  • FlexTableController:用于控制表格的行为,例如监听列宽的变化。
  • dataBuilder:指定如何渲染表格中的数据单元格,默认使用 FlexStripeCellBuilder
  • headers:表格的列名数组。

运行上述代码后,所有列的宽度将相等,并且可以手动调整。


设置列宽

可以通过 initialColumnSizes 参数为每列设置初始宽度。每个宽度由 FlexTableColumnSize 对象定义,支持以下属性:

  • flex:表示列的弹性比例。
  • minFlex:最小弹性比例。
  • maxFlex:最大弹性比例。
  • size:固定宽度。

示例代码:

class MyTableWidgetState extends StatefulWidget {
  final FlexTableController _controller = FlexTableController();

  final List<String> _headers = [
    '小',
    '中',
    '大',
    '有最小值',
    '有最大值',
    '固定大小',
  ];
  final List<FlexTableColumnSize> _sizes = [
    FlexTableColumnSize(flex: 0.5), // 小列
    FlexTableColumnSize(flex: 1.0), // 中列
    FlexTableColumnSize(flex: 2.0), // 大列
    FlexTableColumnSize(minFlex: 1.0), // 最小值约束
    FlexTableColumnSize(maxFlex: 2.0), // 最大值约束
    FlexTableColumnSize(size: 200.0), // 固定宽度
  ];

  [@override](/user/override)
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('列宽设置')),
      body: FlexTable(
        controller: _controller,
        headers: _headers,
        initialColumnSizes: _sizes,
      ),
    );
  }
}

运行效果如图所示:

![InitialColumnSizes]


EmptyDataBuilder

当表格数据为空时,可以使用 EmptyDataBuilder 来显示自定义提示信息。示例代码:

class MyTableWidgetState extends StatefulWidget {
  final FlexTableController _controller = FlexTableController();

  [@override](/user/override)
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return FlexTable(
      controller: _controller,
      emptyDataBuilder: (context) => const Center(
        child: SizedBox(
          width: 100.0,
          height: 100.0,
          child: Material(
            borderRadius: BorderRadius.all(Radius.circular(8.0)),
            color: Colors.black,
            child: Center(
              child: CircularProgressIndicator(
                color: Colors.white,
              ),
            ),
          ),
        ),
      ),
      headers: ['列1', '列2'],
      initialData: [], // 空数据
    );
  }
}

运行效果如图所示:

![EmptyDataBuilder]


数据单元格渲染器

FlexCellBuilder 是一个抽象类,用于自定义表格单元格的渲染方式。以下是几种常见的实现:

FlexDataCellBuilder

默认的数据单元格渲染器,支持简单数据展示。

class MyTableWidgetState extends StatefulWidget {
  final FlexTableController _controller = FlexTableController();

  [@override](/user/override)
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return FlexTable(
      controller: _controller,
      headers: ['列1', '列2'],
      initialData: [
        ['数据1-1', '数据1-2'],
        ['数据2-1', '数据2-2'],
      ],
    );
  }
}

FlexStripeCellBuilder

支持为偶数行和奇数行设置不同的背景颜色。

class MyTableWidgetState extends StatefulWidget {
  final FlexTableController _controller = FlexTableController();

  [@override](/user/override)
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return FlexTable(
      controller: _controller,
      dataBuilder: const FlexStripeCellBuilder(),
      headers: ['列1', '列2'],
      initialData: [
        ['数据1-1', '数据1-2'],
        ['数据2-1', '数据2-2'],
      ],
    );
  }
}

运行效果如图所示:

![FlexStripeCellBuilder]


表头单元格渲染器

FlexHeaderCellBuilder 用于自定义表头单元格的渲染方式。

FlexFilterHeaderCellBuilder

支持通过弹出菜单过滤单列数据。

class MyTableWidgetState extends StatefulWidget {
  final FlexTableController _controller = FlexTableController();
  late final FlexFilterController _filterController =
      FlexFilterController(controller: _controller);

  [@override](/user/override)
  void dispose() {
    _controller.dispose();
    _filterController.dispose();
    super.dispose();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return FlexTable(
      controller: _controller,
      headers: ['列1', '列2'],
      headerBuilder: FlexFilterHeaderCellBuilder(controller: _filterController),
      initialData: [
        ['数据1-1', '数据1-2'],
        ['数据2-1', '数据2-2'],
      ],
    );
  }
}

运行效果如图所示:

![FlexFilterHeaderCellBuilder]


FlexSortHeaderCellBuilder

支持通过点击表头对列进行排序。

class MyTableWidgetState extends StatefulWidget {
  final FlexTableController _controller = FlexTableController();
  late final FlexSortController _sortController =
      FlexSortController(controller: _controller);

  [@override](/user/override)
  void dispose() {
    _controller.dispose();
    _sortController.dispose();
    super.dispose();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return FlexTable(
      controller: _controller,
      headers: ['列1', '列2'],
      headerBuilder: FlexSortHeaderCellBuilder(controller: _sortController),
      initialData: [
        ['数据1-1', '数据1-2'],
        ['数据2-1', '数据2-2'],
      ],
    );
  }
}

更多关于Flutter表格布局插件flexible_table的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter表格布局插件flexible_table的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


flexible_table 是一个用于 Flutter 的表格布局插件,它提供了灵活的表格布局功能,允许开发者轻松创建复杂的表格布局。以下是如何使用 flexible_table 插件的基本步骤:

1. 添加依赖

首先,你需要在 pubspec.yaml 文件中添加 flexible_table 插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  flexible_table: ^1.0.0  # 请使用最新版本

然后运行 flutter pub get 来安装依赖。

2. 导入包

在你的 Dart 文件中导入 flexible_table 包:

import 'package:flexible_table/flexible_table.dart';

3. 创建表格

使用 FlexibleTable 组件来创建表格。你可以通过 columnsrows 属性来定义表格的列和行。

class MyTable extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return FlexibleTable(
      columns: [
        FlexibleTableColumn(title: 'ID', width: 100),
        FlexibleTableColumn(title: 'Name', width: 200),
        FlexibleTableColumn(title: 'Age', width: 100),
      ],
      rows: [
        FlexibleTableRow(cells: [
          FlexibleTableCell(child: Text('1')),
          FlexibleTableCell(child: Text('John Doe')),
          FlexibleTableCell(child: Text('30')),
        ]),
        FlexibleTableRow(cells: [
          FlexibleTableCell(child: Text('2')),
          FlexibleTableCell(child: Text('Jane Smith')),
          FlexibleTableCell(child: Text('25')),
        ]),
      ],
    );
  }
}

4. 自定义表格样式

你可以通过 FlexibleTable 的各种属性来自定义表格的样式,例如边框颜色、背景颜色、行高、列宽等。

FlexibleTable(
  columns: [
    FlexibleTableColumn(title: 'ID', width: 100),
    FlexibleTableColumn(title: 'Name', width: 200),
    FlexibleTableColumn(title: 'Age', width: 100),
  ],
  rows: [
    FlexibleTableRow(cells: [
      FlexibleTableCell(child: Text('1')),
      FlexibleTableCell(child: Text('John Doe')),
      FlexibleTableCell(child: Text('30')),
    ]),
    FlexibleTableRow(cells: [
      FlexibleTableCell(child: Text('2')),
      FlexibleTableCell(child: Text('Jane Smith')),
      FlexibleTableCell(child: Text('25')),
    ]),
  ],
  borderColor: Colors.grey,
  headerBackgroundColor: Colors.blue,
  headerTextStyle: TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
  rowHeight: 50,
);

5. 处理交互

你可以通过 onRowTaponCellTap 来处理行或单元格的点击事件。

FlexibleTable(
  columns: [
    FlexibleTableColumn(title: 'ID', width: 100),
    FlexibleTableColumn(title: 'Name', width: 200),
    FlexibleTableColumn(title: 'Age', width: 100),
  ],
  rows: [
    FlexibleTableRow(cells: [
      FlexibleTableCell(child: Text('1')),
      FlexibleTableCell(child: Text('John Doe')),
      FlexibleTableCell(child: Text('30')),
    ]),
    FlexibleTableRow(cells: [
      FlexibleTableCell(child: Text('2')),
      FlexibleTableCell(child: Text('Jane Smith')),
      FlexibleTableCell(child: Text('25')),
    ]),
  ],
  onRowTap: (rowIndex) {
    print('Row $rowIndex tapped');
  },
  onCellTap: (rowIndex, columnIndex) {
    print('Cell at row $rowIndex, column $columnIndex tapped');
  },
);

6. 动态数据

你可以使用动态数据来生成表格的行和列。例如,从 API 获取数据并动态生成表格。

class MyTable extends StatelessWidget {
  final List<Map<String, dynamic>> data = [
    {'id': 1, 'name': 'John Doe', 'age': 30},
    {'id': 2, 'name': 'Jane Smith', 'age': 25},
  ];

  [@override](/user/override)
  Widget build(BuildContext context) {
    return FlexibleTable(
      columns: [
        FlexibleTableColumn(title: 'ID', width: 100),
        FlexibleTableColumn(title: 'Name', width: 200),
        FlexibleTableColumn(title: 'Age', width: 100),
      ],
      rows: data.map((item) {
        return FlexibleTableRow(cells: [
          FlexibleTableCell(child: Text(item['id'].toString())),
          FlexibleTableCell(child: Text(item['name'])),
          FlexibleTableCell(child: Text(item['age'].toString())),
        ]);
      }).toList(),
    );
  }
}

7. 完整示例

以下是一个完整的示例,展示了如何使用 flexible_table 插件创建一个简单的表格:

import 'package:flutter/material.dart';
import 'package:flexible_table/flexible_table.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Flexible Table Example')),
        body: MyTable(),
      ),
    );
  }
}

class MyTable extends StatelessWidget {
  final List<Map<String, dynamic>> data = [
    {'id': 1, 'name': 'John Doe', 'age': 30},
    {'id': 2, 'name': 'Jane Smith', 'age': 25},
  ];

  [@override](/user/override)
  Widget build(BuildContext context) {
    return FlexibleTable(
      columns: [
        FlexibleTableColumn(title: 'ID', width: 100),
        FlexibleTableColumn(title: 'Name', width: 200),
        FlexibleTableColumn(title: 'Age', width: 100),
      ],
      rows: data.map((item) {
        return FlexibleTableRow(cells: [
          FlexibleTableCell(child: Text(item['id'].toString())),
          FlexibleTableCell(child: Text(item['name'])),
          FlexibleTableCell(child: Text(item['age'].toString())),
        ]);
      }).toList(),
      borderColor: Colors.grey,
      headerBackgroundColor: Colors.blue,
      headerTextStyle: TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
      rowHeight: 50,
      onRowTap: (rowIndex) {
        print('Row $rowIndex tapped');
      },
      onCellTap: (rowIndex, columnIndex) {
        print('Cell at row $rowIndex, column $columnIndex tapped');
      },
    );
  }
}
回到顶部