关于 Flutter
中的 Table
你了解多少,本系列文章将对 Table
进行全面的剖析,让你对 Table
有更全面的了解和使用
本篇文章主要对Table
进行一个介绍,让你对Table
有一个大概的了解,后续将进行更详细的介绍
Table相关属性
dart
Table({
super.key,
// 每一行
this.children = const <TableRow>[],
// 单独定义每列的宽度
this.columnWidths,
// 默认列宽
this.defaultColumnWidth = const FlexColumnWidth(),
// 文字对齐方式
this.textDirection,
// 单元格边框
this.border,
// 单元格对齐方式
this.defaultVerticalAlignment = TableCellVerticalAlignment.top,
// 文本基线
this.textBaseline,
})
下面介绍下 Table 中各个属性的意思
TableColumnWidth 介绍
dart
// 优先级高于`defaultColumnWidth`,同时存在情况下,列宽使用`columnWidths`中的定义
final Map<int, TableColumnWidth>? columnWidths;
// 所有的列表宽都使用这个方式。
final TableColumnWidth defaultColumnWidth;
TableColumnWidth是一个抽象类,一共提供了6种类型,让我们一起看一下
FixedColumnWidth(value),列的宽度为 value 传入的大小
dart
class FixedColumnWidth extends TableColumnWidth {
/// Creates a column width based on a fixed number of logical pixels.
const FixedColumnWidth(this.value);
/// The width the column should occupy in logical pixels.
final double value;
@override
double minIntrinsicWidth(Iterable<RenderBox> cells, double containerWidth) {
return value;
}
@override
double maxIntrinsicWidth(Iterable<RenderBox> cells, double containerWidth) {
return value;
}
}
IntrinsicColumnWidth,根据内容自适应大小
dart
class IntrinsicColumnWidth extends TableColumnWidth {
const IntrinsicColumnWidth({ double? flex }) : _flex = flex;
@override
double minIntrinsicWidth(Iterable<RenderBox> cells, double containerWidth) {
double result = 0.0;
for (final RenderBox cell in cells) {
result = math.max(result, cell.getMinIntrinsicWidth(double.infinity));
}
return result;
}
@override
double maxIntrinsicWidth(Iterable<RenderBox> cells, double containerWidth) {
double result = 0.0;
for (final RenderBox cell in cells) {
result = math.max(result, cell.getMaxIntrinsicWidth(double.infinity));
}
return result;
}
final double? _flex;
@override
double? flex(Iterable<RenderBox> cells) => _flex;
}
MinColumnWidth(a,b) ,比较 a,b 两个TableColumnWidth
取其中最小的
dart
class MinColumnWidth extends TableColumnWidth {
/// Creates a column width that is the minimum of two other column widths.
const MinColumnWidth(this.a, this.b);
/// An upper bound for the width of this column.
final TableColumnWidth a;
/// Another upper bound for the width of this column.
final TableColumnWidth b;
@override
double minIntrinsicWidth(Iterable<RenderBox> cells, double containerWidth) {
return math.min(
a.minIntrinsicWidth(cells, containerWidth),
b.minIntrinsicWidth(cells, containerWidth),
);
}
@override
double maxIntrinsicWidth(Iterable<RenderBox> cells, double containerWidth) {
return math.min(
a.maxIntrinsicWidth(cells, containerWidth),
b.maxIntrinsicWidth(cells, containerWidth),
);
}
@override
double? flex(Iterable<RenderBox> cells) {
final double? aFlex = a.flex(cells);
final double? bFlex = b.flex(cells);
if (aFlex == null) {
return bFlex;
} else if (bFlex == null) {
return aFlex;
}
return math.min(aFlex, bFlex);
}
}
MaxColumnWidth(a,b) ,比较 a,b 两个TableColumnWidth
取其中最大的
dart
class MaxColumnWidth extends TableColumnWidth {
/// Creates a column width that is the maximum of two other column widths.
const MaxColumnWidth(this.a, this.b);
/// A lower bound for the width of this column.
final TableColumnWidth a;
/// Another lower bound for the width of this column.
final TableColumnWidth b;
@override
double minIntrinsicWidth(Iterable<RenderBox> cells, double containerWidth) {
return math.max(
a.minIntrinsicWidth(cells, containerWidth),
b.minIntrinsicWidth(cells, containerWidth),
);
}
@override
double maxIntrinsicWidth(Iterable<RenderBox> cells, double containerWidth) {
return math.max(
a.maxIntrinsicWidth(cells, containerWidth),
b.maxIntrinsicWidth(cells, containerWidth),
);
}
@override
double? flex(Iterable<RenderBox> cells) {
final double? aFlex = a.flex(cells);
final double? bFlex = b.flex(cells);
if (aFlex == null) {
return bFlex;
} else if (bFlex == null) {
return aFlex;
}
return math.max(aFlex, bFlex);
}
}
FractionColumnWidth(value) ,约束的最大 width * value
,如果约束是无限的,则为0
dart
class FractionColumnWidth extends TableColumnWidth {
/// Creates a column width based on a fraction of the table's constraints'
/// maxWidth.
const FractionColumnWidth(this.value);
/// The fraction of the table's constraints' maxWidth that this column should
/// occupy.
final double value;
@override
double minIntrinsicWidth(Iterable<RenderBox> cells, double containerWidth) {
if (!containerWidth.isFinite) {
return 0.0;
}
return value * containerWidth;
}
@override
double maxIntrinsicWidth(Iterable<RenderBox> cells, double containerWidth) {
if (!containerWidth.isFinite) {
return 0.0;
}
return value * containerWidth;
}
}
FlexColumnWidth([this.value = 1.0]) ,和Flex
的效果一样,等分空间
dart
class FlexColumnWidth extends TableColumnWidth {
/// Creates a column width based on a fraction of the remaining space once all
/// the other columns have been laid out.
const FlexColumnWidth([this.value = 1.0]);
/// The fraction of the remaining space once all the other columns have
/// been laid out that this column should occupy.
final double value;
@override
double minIntrinsicWidth(Iterable<RenderBox> cells, double containerWidth) {
return 0.0;
}
@override
double maxIntrinsicWidth(Iterable<RenderBox> cells, double containerWidth) {
return 0.0;
}
@override
double flex(Iterable<RenderBox> cells) {
return value;
}
}
TableRow 介绍
表格中的行
dart
@immutable
class TableRow {
const TableRow({ this.key, this.decoration, this.children = const <Widget>[]});
final LocalKey? key;
// 行的装饰
final Decoration? decoration;
// Widget 必须为 TableCell,每一行的 children 数量必须一致
final List<Widget> children;
}
TableBorder 介绍
dart
const TableBorder({
// 头部
this.top = BorderSide.none,
// 右侧
this.right = BorderSide.none,
// 底部
this.bottom = BorderSide.none,
// 左侧
this.left = BorderSide.none,
// 内部横向
this.horizontalInside = BorderSide.none,
// 内部垂直
this.verticalInside = BorderSide.none,
// radius
this.borderRadius = BorderRadius.zero,
});
用法就和 BoxDecoraiton 里的 Border 一样,只是这里设置的是 Table 的 Border
Table的属性就介绍到这里,没什么复杂的地方,我们主要关注Table的实现和内部的方法,Table内部提供了很多有意思的方法
Table 的构造
dart
class Table extends RenderObjectWidget {
@override
RenderObjectElement createElement() => _TableElement(this);
@override
RenderTable createRenderObject(BuildContext context) {
assert(debugCheckHasDirectionality(context));
return RenderTable(
columns: children.isNotEmpty ? children[0].children.length : 0,
rows: children.length,
columnWidths: columnWidths,
defaultColumnWidth: defaultColumnWidth,
textDirection: textDirection ?? Directionality.of(context),
border: border,
rowDecorations: _rowDecorations,
configuration: createLocalImageConfiguration(context),
defaultVerticalAlignment: defaultVerticalAlignment,
textBaseline: textBaseline,
);
}
@override
void updateRenderObject(BuildContext context, RenderTable renderObject) {
assert(debugCheckHasDirectionality(context));
assert(renderObject.columns == (children.isNotEmpty ? children[0].children.length : 0));
assert(renderObject.rows == children.length);
renderObject
..columnWidths = columnWidths
..defaultColumnWidth = defaultColumnWidth
..textDirection = textDirection ?? Directionality.of(context)
..border = border
..rowDecorations = _rowDecorations
..configuration = createLocalImageConfiguration(context)
..defaultVerticalAlignment = defaultVerticalAlignment
..textBaseline = textBaseline;
}
}
Table
创建的_TableElement
这里就不介绍了,可以自行了解下即可。
通过代码可以看到Table
直接继承自RenderObject
,创建了一个RenderTable
dart
class RenderTable extends RenderBox {
RenderTable({
int? columns,
int? rows,
Map<int, TableColumnWidth>? columnWidths,
TableColumnWidth defaultColumnWidth = const FlexColumnWidth(),
required TextDirection textDirection,
TableBorder? border,
List<Decoration?>? rowDecorations,
ImageConfiguration configuration = ImageConfiguration.empty,
TableCellVerticalAlignment defaultVerticalAlignment = TableCellVerticalAlignment.top,
TextBaseline? textBaseline,
List<List<RenderBox>>? children,
})
}
RenderTable
中内置很多的方法,我们可以使用这些方法对 Table
进行很多操作,我们也可以参照这些方法的实现逻辑,我们也可以参照这些逻辑实现自己的方法。
下面代码中可以看到,只需要使用 GlobalKey
,我们就可以在Table
渲染结束后获取到 RenderTable
,获取到RenderTable
后就可以进行很多有意思的操作了。
dart
class _ExampleState extends State<Example> {
final GlobalKey _tableKey = GlobalKey();
@override
initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
if (_tableKey.currentContext == null) {
return;
}
final renderTable = _tableKey.currentContext!.findRenderObject() as RenderTable;
});
}
@override
Widget build(BuildContext context) {
return Table(
key: _tableKey,
children: [],
);
}
}
本篇文章关于 Table 的介绍就到这里,更多内容后续介绍,感兴趣的可以自行去了解。