Flutter表格布局插件flextable的使用
Flutter表格布局插件FlexTable的使用
FlexTable 是一个可自定义的表格,包含表头、分割视图、冻结视图、自动冻结、缩放和滚动条。表格由模型(model)、视图模型(viewmodel)和构建器(builders)组成。如图1所示,展示了部分选项。FlexTable 支持双向滚动。如果在垂直或水平方向上的滚动偏移小于22.5度超过30个单位长度时,滚动稳定器将介入,防止在多个页面上因过度滚动而漂移。稳定器会纠正交叉滚动方向的漂移,因此可能会看到轻微的摆动。滚动条仅在拖动开始后出现。(移动端)
此外,也可以将 FlexTable 放置在一个 CustomScrollView 中,通过包裹 FlexTable 在一个 adaptive sliver 中实现。包裹在 sliver 中的表格只能在同一时间单向滚动。
使用
要使用此插件,在 pubspec.yaml
文件中添加 flextable
作为依赖项。
开始
要创建一个简单的 FlexTable,首先创建一个模型(DefaultFtModel),然后将其放入 DefaultFlexTable 小部件中。
模型
DefaultFtModel (FtModel<Cell>) 包含数据、行、单元格尺寸、分割选项、自动冻结等。单元格包含值及一些基本的单元格属性:{ 文本样式、对齐方式、背景色、百分比背景色、旋转 }。
final model = DefaultFtModel(
defaultWidthCell: 120.0,
defaultHeightCell: 50.0,
);
model.addCell(
row: 0,
column: 0,
cell: Cell(
value: 'Hello!',
attr: {
CellAttr.textStyle: const TextStyle(fontSize: 20, color: Colors.blue),
},
),
);
// 添加行(见 表格行 段落)
model.horizontalLineList.addLineRange(...);
FlexTable
DefaultFlexTable (FlexTable<FtModel<Cell>, Cell>) 需要 DefaultFtModel 和 DefaultTableBuilder。默认情况下,启用缩放、冻结和分割(从右上角拖动)。可以通过添加 FtController 到 FlexTable 来获取 FtViewModel,以改变例如比例、分割、解锁等设置。
[@override](/user/override)
Widget build(BuildContext context) {
return DefaultFlexTable(
model: model,
tableBuilder: DefaultTableBuilder(),
);
}
FlexTable 在 CustomScrollView 中
FlexTable 可以放置在 CustomScrollView 中,并通过 FlexTableToSliverBox 包装。工作原理是从 FlexTableToSliverBox (RenderSliverSingleBoxAdapter) 确定表格的滚动,通过 constraints.scrollOffset + overlap 来确定滚动,窗口大小由 paintedChildSize 确定。目前在 CustomScrollView 中不支持双向滚动。
final ftController = DefaultFtController();
[@override](/user/override)
Widget build(BuildContext context) {
return CustomScrollView(
slivers: [
// 其他 slivers...
FlexTableToSliverBox(
ftController: ftController,
child: DefaultFlexTable(
model: model,
tableBuilder: DefaultTableBuilder(),
ftController: ftController,
),
),
],
);
}
自定义 FlexTable
目前默认设置较为基础,但可以扩展以下类来更改单元格属性、单元格构建、表格测量、如何接收单元格属性等:
- FtModel<C extends AbstractCell> extends AbstractFtModel<C>
- AbstractTableBuilder<T extends AbstractFtModel<C>, C extends AbstractCell>
- FlexTable<T extends AbstractFtModel<C>, C extends AbstractCell>
- FtController<T extends AbstractFtModel<C>, C extends AbstractCell>
- AbstractCell
表格行
垂直线和水平线分别单独添加到表格中,以减少大表格中的对象数量。TableLinesOneDirection 对象包含一个 LineLinkedList,其中包含 LineRanges,这些 LineRanges 包含一个 LineLinkedList,其中包含 LineNodeRanges 用于一个方向。
垂直线和水平线以范围的形式分别添加到表格中,以最小化大表格中的对象数量。TableLinesOneDirection 对象包含一个 LineLinkedList,其中包含 LineRanges,这些 LineRanges 包含一个 LineLinkedList,其中包含 LineNodeRanges 用于一个方向。
可以通过添加 EmptyLineNodes(带有无线条的 LineNode)覆盖所需范围来删除线条或线条的一部分。TableLinesOneDirection 对象将删除合并了 EmptyLineNode 的线条。如果 LineRange 为空,则自动删除 LineRange。
可以通过使用 Line.change(width:…, color…) 来更改现有线条的宽度和颜色。新的属性将与现有线条合并。
TableLinesOneDirection horizontalLines = TableLinesOneDirection();
// 或者使用已初始化的 FtModel -> ftModel.horizontalLines
const blueLine = Line(
width: 0.5,
color: Color(0xFF42A5F5),
);
/// 0: -- --
/// 1: -- --
/// 2: -- --
horizontalLines.addLineRange(LineRange(
startIndex: 0,
endIndex: 2,
lineNodeRange: LineNodeRange(list: [
LineNode(startIndex: 0, after: blueLine),
LineNode(startIndex: 2, before: blueLine),
LineNode(startIndex: 4, after: blueLine),
LineNode(startIndex: 6, before: blueLine),
]),
));
示例代码
以下是一个完整的示例代码,展示了如何使用 FlexTable。
import 'package:flextable/flextable.dart';
import 'package:flutter/material.dart';
void main() {
runApp(
MaterialApp(
theme: ThemeData(
useMaterial3: true,
colorScheme: ColorScheme.fromSeed(
seedColor: const Color.fromARGB(255, 229, 235, 206))),
home: const ShortExample(),
),
);
}
class ShortExample extends StatefulWidget {
const ShortExample({super.key});
[@override](/user/override)
State<ShortExample> createState() => _ShortExampleState();
}
class _ShortExampleState extends State<ShortExample> {
[@override](/user/override)
Widget build(BuildContext context) {
const columns = 50;
const rows = 5000;
final model = DefaultFtModel(
columnHeader: true,
rowHeader: true,
defaultWidthCell: 120.0,
defaultHeightCell: 50.0,
tableColumns: columns,
tableRows: rows,
);
const line = Line(width: 0.5, color: Color.fromARGB(255, 70, 78, 38));
for (int r = 0; r < rows; r++) {
for (int c = 0; c < columns; c++) {
int rows = 1;
if ((c + 1) % 2 == 0) {
if (r % 3 == 0) {
rows = 3;
} else {
continue;
}
}
Map attr = {
CellAttr.background: (r % 99 < 1
? const Color.fromARGB(255, 249, 250, 245)
: ((r % 2) % 2 == 0
? Colors.white10
: const Color.fromARGB(255, 229, 235, 206))),
CellAttr.textStyle: const TextStyle(
fontSize: 20, color: Color.fromARGB(255, 70, 78, 38)),
};
model.addCell(
row: r,
column: c,
cell: Cell(value: '${numberToCharacter(c)}$r', attr: attr),
rows: rows);
}
}
model.horizontalLines.addLineRanges((create) {
for (int r = 0; r < rows; r += 3) {
/// Horizontal lines
///
///
create(LineRange(
startIndex: r,
lineNodeRange: LineNodeRange(list: [
LineNode(
startIndex: 0,
after: line,
),
LineNode(
startIndex: 0,
before: line,
)
])));
/// Horizontal lines for merged columns
///
///
create(LineRange(
startIndex: r + 1,
endIndex: r + 2,
lineNodeRange: LineNodeRange()
..addLineNodes((create) {
for (int c = 0; c < columns; c += 2) {
create(LineNode(
startIndex: c,
after: line,
));
create(LineNode(
startIndex: c + 1,
before: line,
));
}
})));
}
});
model.verticalLines.addLineRange(LineRange(
startIndex: 0,
endIndex: columns,
lineNodeRange: LineNodeRange(list: [
LineNode(
startIndex: 0,
after: line,
),
LineNode(
startIndex: rows,
before: line,
),
])));
model
..autoFreezeAreasY = [
for (int r = 0; r < rows - 100; r += 99)
AutoFreezeArea(startIndex: r, freezeIndex: r + 3, endIndex: r + 90)
]
..tableColumns = columns
..tableRows = rows;
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: const Text('Short FlexTable example'),
),
body: DefaultFlexTable(
backgroundColor: Colors.white,
model: model,
tableBuilder: DefaultTableBuilder(),
));
}
}
更多关于Flutter表格布局插件flextable的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html