第2章 Material 3 组件中的 Slot 列表:Button、Card、Dialog
Slot(插槽)是 Material 3 组件体系中的核心扩展机制——它允许开发者在保留组件交互逻辑与视觉基准的前提下,向组件内部注入自定义内容或子组件。本章系统梳理三个高频组件(Button、Card、Dialog)的 Slot 定义、数据类型与使用规则,为后续实现章节打下结构化基础。
2.1 Slot 机制概述
在 Material 3 的组件模型中,Slot 是一个具名占位符,组件通过声明 Slot 列表向外界开放内容注入点。每个 Slot 通常绑定一组类型约束(如仅允许 Icon 或 Text 组件),并在组件内部按固定层级渲染。理解 Slot 的命名规范与嵌套关系,是正确使用组件扩展能力的前提。
| 维度 | 说明 |
|---|---|
| 定义位置 | 组件构造函数的参数或子组件属性中声明 |
| 数据类型 | Slot<T>、Slot<Node> 或具体组件类型引用 |
| 渲染时机 | 组件内部按固定顺序依次渲染所有已赋值的 Slot |
| 默认值 | 可提供空 Slot 或占位组件,避免未赋值时出现空白 |
2.2 Button 组件 Slot 列表
Button 系列组件(FilledButton、OutlinedButton、TextButton、ElevatedButton)共享同一套 Slot 接口。以下列出所有可用 Slot 及其类型说明:
| Slot 名称 | 类型约束 | 必填 | 说明 |
|---|---|---|---|
icon | Slot<Icon> | 否 | 位于标签左侧的前置图标,通常为 18dp 尺寸 |
label | Slot<Text> | 是 | 按钮主要文字内容,支持动态文本更新 |
trailingIcon | Slot<Icon> | 否 | 位于标签右侧的后置图标,较少使用 |
overlay | Slot<Box> | 否 | 覆盖在按钮整体上方的内容层,用于加载指示器等 |
label是唯一必填 Slot,即使内容为空字符串也必须传入Text组件。icon与trailingIcon同时赋值时,组件内部按 icon → label → trailingIcon 顺序渲染。overlaySlot 使用Positioned.fill定位,默认不拦截点击事件(需手动设置pointerEvents)。
以下示例展示在 Flutter 中使用 FilledButton 同时赋值 icon 与 label 的典型写法:
FilledButton(
onPressed: () {},
icon: const Icon(Icons.add),
label: const Text('新建任务'),
)
2.3 Card 组件 Slot 列表
Material 3 的 Card 组件提供比 Button 更丰富的 Slot 结构,支持媒体、头部、内容和操作栏四段布局。所有 Slot 均为可选,组件在不赋值时自动隐藏对应区域。
| Slot 名称 | 类型约束 | 默认渲染位置 | 说明 |
|---|---|---|---|
media | Slot<Image> | 顶部全宽区域 | 通常为 16:9 或 4:3 比例的图片,裁剪方式由组件固定 |
header | Slot<Widget> | 媒体下方、内容上方 | 承载标题、副标题、头像等行内组合 |
content | Slot<Text> | 头部下方、操作栏上方 | 主要描述文字,支持文本溢出省略 |
actions | Slot<Row> | 底部右对齐 | 操作按钮组,组件内部自动添加间距与对齐 |
footer | Slot<Widget> | 最底部通栏 | 用于放置元信息、标签或副操作 |
media Slot 的宽高比由 Card 组件的 mediaShape 与 mediaGap 联合控制,传入的图片不会自动裁剪;建议外部预裁剪或使用 BoxFit.cover。
一个包含头部、内容和操作栏的典型 Card 构造片段:
Card(
header: ListTile(
leading: CircleAvatar(child: Text('A')),
title: Text('项目概览'),
subtitle: Text('2025-02-21'),
),
content: const Text('Material 3 Slot API 是组件扩展的核心通道。'),
actions: Row(
children: [
TextButton(onPressed: () {}, label: const Text('详情')),
FilledButton(onPressed: () {}, label: const Text('编辑')),
],
),
)
2.4 Dialog 组件 Slot 列表
Dialog 组件采用“图标—标题—内容—操作”的垂直层叠结构,Slot 定义清晰且类型严格。与 Button 和 Card 不同,Dialog 的 Slot 赋值直接影响对话框的语义层级(如 icon 赋值后组件自动启用顶部圆角与间距调整)。
| Slot 名称 | 类型约束 | 必填 | 说明 |
|---|---|---|---|
icon | Slot<Icon> | 否 | 顶部居中图标,赋值后 Dialog 自动增加上内边距 |
headline | Slot<Text> | 是 | 对话框主标题,使用 24sp 字重 Medium |
content | Slot<Text> | 否 | 正文描述,最大高度受限(可滚动) |
actions | Slot<Row> | 否 | 操作按钮区,组件自动右对齐并添加 8dp 间距 |
icon 与 headline 同时使用时,建议 icon 使用语义明确的 Material 图标(如 Icons.info_outline),且颜色保持 onSurfaceVariant 以对齐 Dialog 的视觉层级。
以下是一个包含完整四层 Slot 的 Dialog 构造示例:
AlertDialog(
icon: const Icon(Icons.warning_amber_rounded),
headline: const Text('确认删除'),
content: const Text('此操作将永久删除所选文件,不可恢复。'),
actions: Row(
children: [
TextButton(onPressed: () {}, label: const Text('取消')),
FilledButton(onPressed: () {}, label: const Text('删除')),
],
),
)
2.5 三个组件 Slot 结构对比
将上述三个组件的 Slot 列表按“层级深度”“必填数量”“类型丰富度”三个维度进行横向比较:
| 组件 | Slot 总数 | 必填数 | 嵌套层级 | 类型严格度 | 典型用途 |
|---|---|---|---|---|---|
| Button | 4 | 1(label) | 1 层(扁平) | 高(Icon/Text 明确) | 操作入口、表单提交 |
| Card | 5 | 0 | 2~3 层(含嵌套 Row/Column) | 中(Widget 宽泛) | 列表项、概览卡片、媒体展示 |
| Dialog | 4 | 1(headline) | 1 层(垂直堆叠) | 高(Icon/Text/Row 明确) | 确认框、提示框、详情弹窗 |
Slot<Widget>),适合高度自定义场景;Button 与 Dialog 则通过窄类型约束保证组件语义一致性。
2.6 Slot 层级关系图
下方 SVG 图展示了 Button、Card、Dialog 三个组件的 Slot 内部渲染层级关系,帮助理解 Slot 在组件树中的实际位置:
2.7 常见误区与调试指引
根据社区反馈与项目实践,以下列出 Slot 使用中最容易踩中的三个误区:
- 将必填 Slot 当作可选处理:Button 的
label与 Dialog 的headline在编译期不会报错,但运行时会导致组件不渲染或布局坍缩。调试时优先检查必填 Slot 是否已赋值。 - Slot 类型不匹配导致隐式转换失败:部分组件内部使用
is判断 Slot 类型,传入Container而非Icon可能导致图标区空白。应严格遵循类型约束表。 - 多个 Slot 同时赋值时的顺序依赖:Card 的
header与content都依赖media的间距计算;若media为空但header存在,组件仍会保留媒体占位空间。建议按 media → header → content → actions → footer 顺序赋值。
SlotInspector 或打印 widget.slotList 运行时信息,可以快速确认每个 Slot 的赋值状态与类型。对于 Web 端(Lit/Material Web),使用浏览器 DevTools 的组件树面板查看 Slot 节点是否被正确分发。
2.8 稳定性与性能提示
Slot 机制本身不会引入额外性能开销——组件内部仅在构建时遍历 Slot 列表一次。但在以下场景中需要关注优化:
- 动态 Slot 切换:频繁替换
icon或content时,建议使用key属性保持组件状态稳定,避免不必要的重建。 - 大体积 Slot 内容:Card 的
mediaSlot 传入高分辨率图片时,应在外部预先缩放至组件所需尺寸,防止组件内部多次 layout 计算。 - 嵌套 Slot 层级过深:Dialog 的
actionsSlot 内部尽量避免再嵌套多层 Row/Column,以降低布局计算复杂度。
至此,Button、Card、Dialog 三个核心组件的 Slot 列表已完整呈现。下一维度将进入 Slot 的类型系统与类型安全约束详解,为自定义组件 Slot 设计提供类型理论基础。