Skip to content

形状 — Shapes / AppShapes ​

圆角的两个入口:M3 的语义档位(跟主题走)和 AppShapes 的命名形状(按用途命名)。

基本用法 ​

kotlin
Surface(shape = MaterialTheme.shapes.medium) { /* … */ }   // 优先:语义档位
Surface(shape = AppShapes.card) { /* … */ }                // 命名形状
Surface(shape = AppShapes.heroTop) { /* … */ }             // 不对称圆角(只圆上边)

参数 ​

M3 形状档位 Shapes ​

字段值
extraSmall8.dp
small12.dp
medium16.dp
large24.dp
extraLarge32.dp

命名形状 AppShapes ​

名称值用在哪
card四角 24dp标准卡片:内容卡片、设置分组、资产卡
cardSmall四角 16dp小卡片:二级卡片、弹窗内块、下拉菜单
row四角 16dp列表行(整行当一张卡时用)
heroTop上 28dp / 下直角折叠标题栏的内容卡片
sheetTop上 28dp / 下直角底部弹层、底部导航上沿
iconContainer12dp列表项左侧图标容器
iconContainerLarge16dp大图标容器:应用图标、头像占位、空态图标
pill50%(胶囊)按钮、标签、chip
badge6dp小角标:Update 标记、数量徽标
textField12dp输入框(单行与多行都是这一档)

要点 ​

  • 优先取 M3 语义档位,不要现写 dp。 MaterialTheme.shapes.medium 这类跟着主题走;AppShapes 是给「档位表达不了」的形态准备的 —— 不对称圆角、胶囊、内层收紧的图标容器。
  • 内层要比外层小一档。 卡片 24dp,卡片内的图标容器只用 12dp;大圆角套大圆角会糊成一团。
  • 输入框的单行与多行共用 textField(12dp)。 单行早前跟按钮走 pill 胶囊,加浮动标签时换掉了 —— 一传 label,两个形态都要有一圈带缺口的描边(标签压在边线上、边线在标签处开口),胶囊那段圆弧放不下缺口。所以两个形态一起锁在 12dp(这圈描边现在由 M3 OutlinedTextField 画,组件库只锁圆角)。
  • heroTop 和 sheetTop 值相同但语义不同,别互相替代 —— 一个说「折叠标题栏的内容卡片」,一个说「底部弹层上沿」,将来只改其中一个时不会误伤另一个。
  • row 和 cardSmall 也是同值(16dp)不同语义,同理。

说明 ​

  • 圆角整体比 M3 基线更大:M3 基线 large = 16dp / extraLarge = 28dp,这里是 24dp / 32dp。这是 M3 Expressive 的有意放大 —— 观感更「软」、更有表现力。
  • 不对称圆角是 Expressive 的特征手法:一侧大圆角、一侧直角,用来制造方向感。heroTop 就是典型 —— 上沿柔和地压在壁纸上,下沿保持直角与屏幕边缘融为一体,滚动时视觉上是「卡片从头部滑出来」。
  • 命名形状的价值是「改一处、全站同步」,避免同一个 24dp 在十个文件里各写一遍。
  • iconContainerLarge 是 16dp 而不是 12dp:它服务的图标容器本身是 72dp 起(空态、错误态),比列表项的 48dp 大一圈,圆角跟着放大一档才协调。