Flutter表格布局插件flexible_table的使用
Flutter表格布局插件flexible_table的使用
在本教程中,我们将介绍如何使用Flutter中的flexible_table
插件来创建一个具有灵活列宽、固定表头且支持过滤和排序功能的表格。该插件还支持处理非常大的数据集,并提供了多种自定义选项。
引言
FlexTable
是 flexible_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
更多关于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
组件来创建表格。你可以通过 columns
和 rows
属性来定义表格的列和行。
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. 处理交互
你可以通过 onRowTap
或 onCellTap
来处理行或单元格的点击事件。
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');
},
);
}
}