Skip to content

字阶 — Typography / NumberStyles ​

全站排版的唯一来源。页面里不要写 fontSize / fontWeight / letterSpacing。

基本用法 ​

kotlin
Text("标题", style = MaterialTheme.typography.titleMedium)
Text("正文", style = MaterialTheme.typography.bodyMedium)

// 会变宽度的数字必须等宽,否则整行左右抖
Text(balance.toString(), style = NumberStyles.display)
Text("$count 次", style = NumberStyles.title)

临时给任意样式开等宽数字:

kotlin
Text("12:34", style = MaterialTheme.typography.titleLarge.tabular())

参数 ​

15 级字阶 Typography ​

用 MaterialTheme.typography.xxx 取。

档位字号行高字距字重用在哪
displayLarge57sp64sp-0.25spBold大数字、全屏展示
displayMedium45sp52sp0Bold
displaySmall36sp44sp0Bold空态主文案、NumberStyles.display 的基底
headlineLarge32sp40sp-0.2spBlack折叠标题栏
headlineMedium28sp36sp0Black普通标题栏(TopTitleBar 默认取这条)
headlineSmall24sp32sp0SemiBold区块小标题
titleLarge22sp28sp0SemiBold
titleMedium16sp24sp0.15spSemiBold卡片标题、列表项标题、菜单选中项
titleSmall14sp20sp0.1spSemiBold弹窗标题、空态主文案、提示条标题
bodyLarge16sp26sp0.5spNormal正文、菜单项
bodyMedium14sp22sp0.25spNormal次要正文、错误说明
bodySmall12sp18sp0.4spNormal副标题、说明文案
labelLarge14sp20sp0.1spMedium按钮文字
labelMedium12sp16sp0.5spMedium标签、小号辅助文案
labelSmall11sp16sp0.5spMedium角标

数字字阶 NumberStyles ​

三档都开了 tnum(等宽数字):

名称基于字重用在哪
displaydisplaySmallBold资产卡余额、统计值
titletitleMediumSemiBold列表右侧计数
labellabelMediumMedium角标、百分比

要点 ​

  • 字重只走字阶,页面里不要再手写 FontWeight。 约定是:Bold(700) = 页面大标题 / 折叠标题栏;SemiBold(600) = 区块与卡片标题、headlineSmall;Medium(500) = 标签与按钮;Normal(400) = 正文。
  • 会变宽度的数字必须用 NumberStyles 或 .tabular()。 默认是比例数字,1 比 8 窄 —— 余额、观看次数、版本号、下载进度一变,整行就左右抖。
  • 大字号收紧字距、小字号放开字距。 display* / headlineLarge 是负字距,label* 是正字距。这是按字号校准过的,不要覆盖。
  • 行高比 M3 英文基线略大,因为中文比拉丁文高。多行中文靠这个才不挤在一起。
  • 字体是系统默认(FontFamily.Default),不内嵌第三方字体 —— 各厂商 ROM 自带的中文黑体已是现代字体,内嵌会让 APK 多出十几 MB。

已知的代码与注释不一致

Type.kt 的注释声称 headlineLarge / headlineMedium 已经从 FontWeight.Black 改成 Bold,但代码里的实际值仍是 FontWeight.Black。上表以代码为准。任何直接引用这两个 token 的组件(例如 TopTitleBar)拿到的是 Black(900);折叠标题栏和登录页大标题不受影响,因为它们是自己手写 FontWeight.Bold 的。

说明 ​

  • 「字体家族可替换、字阶与字重是骨架」:这一套和 Material 3 Expressive 的思路一致 —— 换字体只需要替换 fontFamily,其余不动。
  • 刻意不用 Black(900)(headline* 两处例外,见上面的 warning):中文黑体在 900 下笔画会糊成一团,加大字重反而降低辨识度。大标题靠 Bold + 负字距就够有分量。
  • NumberStyles 的三档是「取同名 token 再压字重」,只额外加了 fontFeatureSettings = "tnum"。它们和本文件那套自定义 Typography 在同名字号 / 行高 / 字距上是一致的,所以两者混用不会跳。
  • display* 三档没有负字距之外的特殊处理:displayMedium / displaySmall 是 0 字距,只有最大的 displayLarge 收 -0.25sp —— 字号越大越需要收,但不是所有大字号都需要收。