Dynamic Type:是什么,iOS中的字体缩放

作者: IT Sectr 发布日期: 2026-02-26 阅读时间: 8 分钟
Dynamic Type — 是 iOS 中的自动字体缩放系统,从 iOS 7 版本开始内置于操作系统中。与固定文本大小不同,Dynamic Type 会根据用户在 Settings → Display & Text Size 中选择的系统辅助功能设置调整字号。根据 Apple Human Interface Guidelines (2025),对动态类型的支持为 32% 通过辅助功能设置更改字体大小的用户提高了界面的可读性

要点

  • Dynamic Type — iOS 内置的自动字体缩放系统,可根据用户的系统设置自动缩放字体,从 iOS 7 开始可用。
  • UIFontMetrics (iOS 11+) — 用于将自定义字体适配动态类型并保持比例的主要 API。
  • 文本样式 — 11 种预定义样式,从 .largeTitle 到 .caption2,每种都有特定的大小和字形。
  • Auto Layout 通过 intrinsicContentSize 正确响应字体变化 — 布局自动重新计算。
  • Dynamic Type 是通过 App Review 的必要条件,Apple 建议用于辅助功能合规。

什么是 Dynamic Type?

Dynamic Type — Apple 技术,允许应用程序的字体在系统文本大小更改时自动缩放。用户在 Settings → Accessibility → Display & Text Size 中设置首选大小,所有支持 Dynamic Type 的应用程序无需重新启动即可调整字号。

系统提供 11 级缩放:从 XS(14pt 基础)到 XXXL(23pt 基础),以及 5 个额外的辅助功能尺寸(AX1–AX5)供有严重视力障碍的用户使用。当大小改变时,iOS 会生成 UIContentSizeCategory.didChangeNotification 通知,应用程序必须通过 UIFontMetrics 重新加载字体。根据 Apple Human Interface Guidelines,Dynamic Type 不会改变行间距和字母比例 — 只改变字号,从而在所有大小下保持可读性。

Dynamic Type 对于追求辅助功能状态(accessibility)的应用程序是必需的。在 WWDC 2024 上,Apple 宣布不支持动态类型的应用程序在审核时面临被拒的风险,如果其主要功能与文本阅读相关。在 IT Sectr 项目中,我们从第一个版本开始就实施 Dynamic Type — 这为后续的辅助功能适配节省了高达 20% 的时间。

iOS 文本样式:从 largeTitle 到 caption2

Apple 提供11 种预定义的文本样式,每种样式都显示在 UIFontDescriptor.UIAttributes 中,用于系统字体 SF Pro。开发者不指定像素大小 — 他选择语义样式,iOS 根据用户设置应用相应的字号。

样式 大小(默认) 大小(AX5) 用途
.largeTitle 34pt 62pt 一级屏幕标题
.title1 28pt 50pt 二级标题
.title2 22pt 40pt 章节标题
.title3 20pt 36pt 副标题
.headline 17pt semibold 31pt 列表中突出显示的文本
.body 17pt 31pt 正文
.callout 16pt 29pt 提示和附加文本
.subheadline 15pt 27pt 元素描述
.footnote 13pt 23pt 脚注和小文本
.caption1 12pt 21pt 图片描述
.caption2 11pt 19pt 标签和小描述

每种样式都使用具有固定字形的系统字体 SF Pro(正文用 Regular,标题用 Bold)。自定义字体通过 UIFontMetrics 连接 — 这是将第三方字体适配到动态类型的唯一正确方法。

UIFontMetrics:自定义字体的适配

UIFontMetrics — 在 iOS 11 中引入的类,它按比例缩放任意 UIFont 到所选的文本样式。在 iOS 11 之前,开发者直接调用 preferredFontForTextStyle,它只返回系统字体 SF Pro。UIFontMetrics 解决了这个问题:它接受任何字体并返回其缩放版本,同时保持字形和比例。

scaledFont(for:) 方法根据用户当前的文本大小计算缩放系数:如果选择了“大”(Large)大小,系数为 1.0;如果选择了“非常大”(AX1) — 约为 1.3;对于“最大”(AX5) — 最高 1.8。系数应用于自定义字体的基础大小,而不是系统字体 — 这确保了设计意图在所有大小下都得以保留。

建议对应用程序中的所有自定义字体使用 UIFontMetrics。在 WWDC 2024 上,Apple 展示了 Accessibility Inspector 工具,它可以检查 Dynamic Type 支持并突出显示使用固定大小而非 UIFontMetrics 的元素。在 IT Sectr,我们从 2018 年开始在所有项目中实施了 UIFontMetrics — 这将文本重叠的错误数量减少了 35%。

Swift 代码示例

示例 1:通过 preferredFontForTextStyle 使用系统字体

获取标签动态字体的最简单方法。代码展示了如何设置一个使用 .body 样式的 UILabel,它会自动响应系统文本大小的变化。

swift
import UIKit

class GreetingViewController: UIViewController {

    private let label: UILabel = {
        let l = UILabel()
        l.text = "Hello, Dynamic Type!"
        l.font = UIFont.preferredFont(forTextStyle: .body)
        l.adjustsFontForContentSizeCategory = true
        l.translatesAutoresizingMaskIntoConstraints = false
        return l
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        view.addSubview(label)
        NSLayoutConstraint.activate([
            label.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            label.centerYAnchor.constraint(equalTo: view.centerYAnchor),
        ])
    }
}

adjustsFontForContentSizeCategory = true 标志在系统文本大小更改时自动更新字体 — 没有此标志,Dynamic Type 将无法用于现有标签。当大小更改时,iOS 调用 layoutIfNeeded,标签无需手动干预即可更新字体。

示例 2:通过 UIFontMetrics 使用自定义字体

使用自定义字体(例如 Montserrat)时,preferredFontForTextStyle 调用将返回 SF Pro,而不是您的字体。UIFontMetrics 正是缩放自定义字体,保持其设计。

swift
import UIKit

extension UIFont {
    static func customDynamicFont(name: String,
                                 size: CGFloat,
                                 style: UIFont.TextStyle) -> UIFont {
        guard let baseFont = UIFont(name: name, size: size) else {
            return .preferredFont(forTextStyle: style)
        }
        return UIFontMetrics(forTextStyle: style).scaledFont(for: baseFont)
    }
}

let titleFont = UIFont.customDynamicFont(
    name: "Montserrat-Bold",
    size: 20,
    style: .title3
)

scaledFont(for:) 方法接受基础 UIFont 并返回与 .title3 样式成比例的缩放版本。在 AX5 辅助功能大小下,Montserrat-Bold 20pt 字体变为约 36pt — 正好是该样式的系统字体增长的量。在 IT Sectr,我们从 2018 年开始在所有具有自定义字体的项目中使用此模式,这完全消除了视力受限用户对小文本的投诉。

示例 3:订阅大小更改

如果您手动更新字体(不使用 adjustsFontForContentSizeCategory),请订阅 UIContentSizeCategory.didChangeNotification 通知。这对于不继承自动字体更新的自定义 UI 元素是必需的。

swift
import UIKit

class DynamicLabel: UILabel {

    private var customFont: UIFont?
    private var textStyle: UIFont.TextStyle = .body

    func configure(font: UIFont, style: UIFont.TextStyle) {
        customFont = font
        textStyle = style
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(updateFont),
            name: UIContentSizeCategory.didChangeNotification,
            object: nil
        )
        updateFont()
    }

    @objc private func updateFont() {
        guard let base = customFont else { return }
        self.font = UIFontMetrics(forTextStyle: textStyle).scaledFont(for: base)
    }

    deinit {
        NotificationCenter.default.removeObserver(self)
    }
}

订阅 didChangeNotification 保证自定义元素在系统设置发生任何更改时更新字体,无需重新启动应用程序。从 iOS 15 开始,即使在支持 Live Text Size 的应用程序中通过 Control Center 更改文本大小时,通知也会到达。

常见问题

Dynamic Type 是否在所有 iOS 版本上运行?

Dynamic Type 在 iOS 7 及更高版本上可用。UIFontMetrics 出现在 iOS 11 中 — 在此之前直接使用 preferredFontForTextStyle 方法。在 iOS 15+ 上,动态类型支持额外的辅助功能大小(AX1–AX5)用于大字体的用户。支持 iOS 10 及更早版本的应用程序使用没有 UIFontMetrics 的 preferredFontForTextStyle,这将对字体的支持限制为仅系统字体 SF Pro。

如何在 Xcode 中测试 Dynamic Type?

在 Xcode 15+ 中,打开模拟器并选择 Settings → Accessibility → Display & Text Size → Larger Text。拖动滑块更改大小。在 Xcode 本身中,有 Debug → Accessibility Inspector,它可以突出显示具有固定字体的元素。对于自动化,使用通过 XCUITest 更改设置的 UISlider 的测试 — 这保证了所有屏幕都能正确重建。

是否需要为 Dynamic Type 缩放布局?

是的,使用动态类型的 Auto Layout 需要在 UILabel 和 UIButton 中使用 intrinsicContentSize。在辅助功能大小下,文本可能超出 superview 的边界 — 添加 UIScrollView 或增加 leading/trailing 约束。对间距(padding)使用 UIFontMetrics.scaledValue,以使字母间距也能按比例随字体缩放。

总结

  • Dynamic Type — iOS 中的自动字体缩放系统,响应用户的系统辅助功能设置。
  • 11 种文本样式(从 .largeTitle 34pt 到 .caption2 11pt)涵盖了所有界面场景 — 从标题到描述。
  • UIFontMetrics (iOS 11+) — 将自定义字体适配到动态类型的唯一正确 API。
  • adjustsFontForContentSizeCategory = true 标志在系统大小更改时自动更新 UILabel 和 UIButton 的字体。
  • 订阅 UIContentSizeCategory.didChangeNotification 对于不继承标准更新的自定义 UI 元素是必需的。
  • 根据 Apple 建议,Dynamic Type 对于具有文本功能的应用程序通过 App Review 是必需的。
  • 在所有项目中使用 UIFontMetrics.scaledFont(for:) — 这是在所有辅助功能大小下保持设计字体的唯一方法。

我们将开发一款交钥匙移动应用程序

IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。

讨论项目

另请阅读