外观
形状 — Shapes / AppShapes
圆角的两个入口:M3 的语义档位(跟主题走)和 AppShapes 的命名形状(按用途命名)。
基本用法
kotlin
Surface(shape = MaterialTheme.shapes.medium) { /* … */ } // 优先:语义档位
Surface(shape = AppShapes.card) { /* … */ } // 命名形状
Surface(shape = AppShapes.heroTop) { /* … */ } // 不对称圆角(只圆上边)参数
M3 形状档位 Shapes
| 字段 | 值 |
|---|---|
extraSmall | 8.dp |
small | 12.dp |
medium | 16.dp |
large | 24.dp |
extraLarge | 32.dp |
命名形状 AppShapes
| 名称 | 值 | 用在哪 |
|---|---|---|
card | 四角 24dp | 标准卡片:内容卡片、设置分组、资产卡 |
cardSmall | 四角 16dp | 小卡片:二级卡片、弹窗内块、下拉菜单 |
row | 四角 16dp | 列表行(整行当一张卡时用) |
heroTop | 上 28dp / 下直角 | 折叠标题栏的内容卡片 |
sheetTop | 上 28dp / 下直角 | 底部弹层、底部导航上沿 |
iconContainer | 12dp | 列表项左侧图标容器 |
iconContainerLarge | 16dp | 大图标容器:应用图标、头像占位、空态图标 |
pill | 50%(胶囊) | 按钮、标签、chip |
badge | 6dp | 小角标:Update 标记、数量徽标 |
textField | 12dp | 输入框(单行与多行都是这一档) |
要点
- 优先取 M3 语义档位,不要现写 dp。
MaterialTheme.shapes.medium这类跟着主题走;AppShapes是给「档位表达不了」的形态准备的 —— 不对称圆角、胶囊、内层收紧的图标容器。 - 内层要比外层小一档。 卡片 24dp,卡片内的图标容器只用 12dp;大圆角套大圆角会糊成一团。
- 输入框的单行与多行共用
textField(12dp)。 单行早前跟按钮走pill胶囊,加浮动标签时换掉了 —— 一传label,两个形态都要有一圈带缺口的描边(标签压在边线上、边线在标签处开口),胶囊那段圆弧放不下缺口。所以两个形态一起锁在 12dp(这圈描边现在由 M3OutlinedTextField画,组件库只锁圆角)。 heroTop和sheetTop值相同但语义不同,别互相替代 —— 一个说「折叠标题栏的内容卡片」,一个说「底部弹层上沿」,将来只改其中一个时不会误伤另一个。row和cardSmall也是同值(16dp)不同语义,同理。
说明
- 圆角整体比 M3 基线更大:M3 基线
large = 16dp/extraLarge = 28dp,这里是24dp/32dp。这是 M3 Expressive 的有意放大 —— 观感更「软」、更有表现力。 - 不对称圆角是 Expressive 的特征手法:一侧大圆角、一侧直角,用来制造方向感。
heroTop就是典型 —— 上沿柔和地压在壁纸上,下沿保持直角与屏幕边缘融为一体,滚动时视觉上是「卡片从头部滑出来」。 - 命名形状的价值是「改一处、全站同步」,避免同一个 24dp 在十个文件里各写一遍。
iconContainerLarge是 16dp 而不是 12dp:它服务的图标容器本身是 72dp 起(空态、错误态),比列表项的 48dp 大一圈,圆角跟着放大一档才协调。