Flutter 布局网格
Flutter 的基于网格的布局系统,针对用户界面设计进行了优化,灵感来自 CSS Grid Layout。
✨特色:✨
- 固定、灵活和基于内容的行和列大小调整
- 精确控制项目放置(如果需要),包括跨行、跨列
和重叠项目 - 一个可配置的自动网格项目放置算法,能够稀疏和密集地填充跨
行和列 - 右到左支持,由环境 `Directionality` 或配置驱动
- 间隙!
入门
本库使用的所有术语均与 CSS Grid Layout 规范共享。如果您
不熟悉,我建议您查看MDN 的网格
术语词汇表。
要包含在您的 pubspec 中,请参阅
pub.dev.
示例
这是您可以在上面看到的示例的来源。
const cellRed = Color(0xffc73232);
const cellMustard = Color(0xffd7aa22);
const cellGrey = Color(0xffcfd4e0);
const cellBlue = Color(0xff1553be);
const background = Color(0xff242830);
class Piet extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
color: background,
child: LayoutGrid(
columnGap: 12,
rowGap: 12,
templateColumnSizes: [
FlexibleTrackSize(1),
FlexibleTrackSize(3.5),
FlexibleTrackSize(1.3),
FlexibleTrackSize(1.3),
FlexibleTrackSize(1.3),
],
templateRowSizes: [
FlexibleTrackSize(1),
FlexibleTrackSize(0.3),
FlexibleTrackSize(1.5),
FlexibleTrackSize(1.2),
],
children: [
// Column 1
GridPlacement(
columnStart: 0,
rowStart: 0, rowSpan: 2,
child: _buildItemForColor(cellRed),
),
GridPlacement(
columnStart: 0,
rowStart: 2, rowSpan: 2,
child: _buildItemForColor(cellMustard),
),
// Column 2
GridPlacement(
columnStart: 1,
rowStart: 0, rowSpan: 4,
child: _buildItemForColor(cellRed),
),
// Column 3
GridPlacement(
columnStart: 2, columnSpan: 3,
rowStart: 0,
child: _buildItemForColor(cellBlue),
),
GridPlacement(
columnStart: 2, columnSpan: 3,
rowStart: 1, rowSpan: 2,
child: _buildItemForColor(cellMustard),
),
GridPlacement(
columnStart: 2,
rowStart: 3,
child: _buildItemForColor(cellGrey),
),
// Column 4
GridPlacement(
columnStart: 3,
rowStart: 3,
child: _buildItemForColor(cellBlue),
),
// Column 5
GridPlacement(
columnStart: 4,
rowStart: 3,
child: _buildItemForColor(cellMustard),
),
],
),
);
}
Widget _buildItemForColor(Color c) =>
DecoratedBox(decoration: BoxDecoration(color: c));
}
用法
列和行的尺寸调整
目前有三种方法可以调整轨道(行或列)的大小
- `FlexibleSizeTrack` — 初始布局完成后消耗剩余空间。
- `FixedSizeTrack` — 在轴上占用特定数量的像素
- `IntrinsicContentTrackSize` — 调整大小以包含其项目的内容。也将扩展以填充
可用空间,一旦 `FlexibleTrackSize` 轨道有机会。
技术上讲,您可以定义自己的,但我不会这样做,因为 API 可能会发生变化。
将小部件放置在 `LayoutGrid` 中
当 `LayoutGrid.children` 提供任意小部件时,它将被分配一个单元格,并
根据 `LayoutGrid.autoPlacement` 算法自动放置(此处
描述)。
LayoutGrid(
templateColumnSizes = [/*...*/];
templateRowSizes = [/*...*/];
children: [
MyWidget(), // Will occupy a 1x1 in the first vacant cell
],
)
通过 `GridPlacement` 小部件可以精确控制项目的位置。您可以将
`GridPlacement` 视为
`Positioned` 的等价物
对于 `LayoutGrid` — 它控制小部件的放置位置及其占用的单元格。
LayoutGrid(
templateColumnSizes = [/*...*/];
templateRowSizes = [/*...*/];
children: [
GridPlacement(
// All parameters optional
columnStart: 1,
columnSpan: 3,
rowStart: 5,
rowSpan: 2,
child: MyWidget(),
),
],
)
`GridPlacement` 的所有构造函数参数都是可选的。它默认为 1x1 网格项
将由网格自动放置。指定定位或跨越信息(通过
`columnStart`/`columnSpan`/`rowStart`/`rowSpan` 参数)将为
其算法提供额外的约束。
明确放置的项目(即提供了 `columnStart` 和 `rowStart`)将始终
被精确放置,即使它与其他明确放置的项目重叠。自动放置的项目
将围绕明确放置的项目流动。
可访问性和放置
请注意,您通过放置在视觉上传达的含义在呈现时可能不清晰
通过辅助技术,因为 Flutter 默认以源代码顺序公开信息。
在您的语义(视觉)顺序与源代码顺序不同的情况下,
顺序可以通过 `Semantics` 小部件的
`sortKey` 参数进行配置。
与 CSS Grid Layout 的区别
CSS Grid Layout 中不支持的内容
- 负数的行/列开始/结束。在 CSS 中,这些值指的是相对于网格
轴末尾的位置。 - 显式网格之外的任何单元格。如果项目放置在您的
行/列模板定义的区域之外,我们将引发错误。支持自动添加行和列
以适应超出边界的项目正在考虑中。 - minmax()、百分比、宽高比轨道尺寸调整
- 命名模板区域,尽管它们即将推出
区别
- 在 `flutter_layout_grid` 中,灵活轨道不考虑其内容的基线尺寸,而在 CSS 中会。
测量成本很高,我选择了速度。 - 总和小于 1 的灵活轨道
为什么不用 Slivers?
本库不是 Sliver 驱动的。我
曾考虑过,但我的用例需要行和列的基于内容的尺寸调整,并且我不想
弄清楚滚动时调整轨道大小的 UI 挑战。我可能会在某个时候
有兴趣承担这些。
路线图
- [ ] 测试!
- [ ] 命名模板区域,用于更友好的项目放置
- [ ] 改进的轨道尺寸调整,包括最小/最大和宽高比
- [ ] 通过委托在特定行位置指定行和列间隙的能力
- [ ] 隐式网格支持(在添加子项时沿轴自动增长)
- [ ] 性能改进,只要我能让这个分析器运行(!!!)