04 · 布局¶
分工¶
| 负责方 | 管什么 |
|---|---|
| Style | 本盒 width/height、min/max、padding、margin、overflow |
| 布局容器 | 子节点如何排列:方向、gap、对齐、flex 增长、滚动 |
不要试图用 Style 表达「兄弟间距」或「flex grow」——那些在 Row / Column 等方法上。
常用容器¶
Box¶
单子节点外壳;可带 Key、点击、Style:
可交互:
ui.Box(ui.Text("点我")).
Key("tap").
OnClick(func() { send(Tapped{}) }).
Style(ui.Padding(8).Cursor(ui.CursorPointer))
Row / Column¶
ui.Column(
ui.Text("标题").Size(20),
ui.Row(
ui.Button("a", ui.Text("A")).OnClick(...),
ui.Button("b", ui.Text("B")).OnClick(...),
).Gap(8),
).Gap(12)
常用方法:
Gap(n)— 子项间距AlignStart/AlignMiddle/AlignEnd等 — 交叉轴对齐- 配合
Flexible/Expanded分配剩余空间(见示例examples/layout)
Center¶
在可用空间中居中子树:
Scroll¶
内容超出时滚动:
视觉外扩与裁剪¶
Scroll、List、Scrollbar 和 SplitPane 会自动为 Style 的阴影和
轮廓在视口内部预留空间;Input、Card 等使用公共 Box 外壳的组件无需额外
添加 margin。安全空间只出现在视口边缘,不会被加到每两个列表项之间。
显式的 OverflowHidden 仍是本地裁剪边界;已被该边界裁掉的子内容不会再影响
外层视口。
自绘超出盒子边界的内容可通过 VisualOutset 声明最小范围,或在没有 Style
外壳时使用 LayoutVisualOutset:
ui.Box(customCanvas).Style(
ui.VisualOutset(6, 8, 10, 8),
)
// 直接自绘时:top, right, bottom, left。
ui.LayoutVisualOutset(ctx, gtx, customCanvas, 6, 8, 10, 8)
首次发现新的外扩范围时,视口会请求下一帧完成安全边距布局。它不会让这类 绘制越过滚动视口或窗口边界。
Grid / Wrap / Stack / SplitPane¶
| 容器 | 用途 |
|---|---|
Grid |
网格 |
Wrap |
自动换行流式排列 |
Stack |
叠放 |
SplitPane |
可拖分割条 |
Surface / Card |
带主题表面/卡片语义的容器 |
完整演示:examples/layout、examples/grid_layout、examples/split_panes、examples/scrollbars。
尺寸怎么设¶
尺寸写在 Style 上,再交给 Box 或控件的 .Style(...):
ui.Box(
ui.Input("name", m.Name).OnChange(...),
).Style(ui.Width(320))
// 或
ui.Box(child).Style(
ui.Width(200).
Height(40).
MinWidth(120).
MaxWidth(400).
Padding(12).
Margin(4),
)
宽高比:
约束直觉¶
父级给出 最大可用空间;子级在约束内声明自己的尺寸与排列。 Fill / 百分比类能力通过 Style 与容器策略配合(详见规格 03,应用侧记「父约束 → 子声明」即可)。
典型页面骨架¶
func View(_ *ui.Context, m Model, send ui.Send[Msg]) ui.Widget {
return ui.Column(
ui.WindowTitleBar(...), // 或自定义顶栏
ui.Row(
ui.Sidebar(...),
ui.Expanded(
ui.Scroll(
"page-content",
ui.Column(
// 主内容
).Gap(16).Style(ui.Padding(24)),
),
),
),
ui.StatusBar(...),
)
}
(具体 API 以组件文档与示例为准;骨架思想是「列/行嵌套 + Scroll + Style 内边距」。)
注意¶
- 每帧重建 Widget 树是正常的;不要缓存可变 Widget 状态。
- 有状态控件必须有稳定 Key。
- 列表项 Key 用业务 id,不要用仅与渲染顺序绑定的临时下标(若顺序会变)。