Make your app visually accessible
Accessibility 入门 22m

让你的 App 视觉上更无障碍

Make your app visually accessible

2020年6月23日

在 Apple 官方观看视频

一句话判断

视觉无障碍不只是加个 VoiceOver 标注——这场 Session 从颜色对比度、动态字体到反转颜色适配,系统性地讲了如何让你的 App 对视觉障碍用户真正可用。

这场 Session 讲了什么

Session 从三个维度讲解视觉无障碍:色彩、排版和视觉适配。在色彩方面,强调不能仅依赖颜色来传达信息(如红色表示错误),需要配合图标或文字标签。介绍了 WCAG 2.1 的色彩对比度标准:普通文本至少 4.5:1,大号文本至少 3:1。

在排版方面,Dynamic Type 是核心。如果你的 App 使用系统字体并正确配置 Auto Layout,Dynamic Type 大部分情况下自动生效。但自定义字体需要额外处理——通过 UIFontMetrics 为自定义字体提供缩放支持。

在视觉适配方面,Session 介绍了 Smart Invert Colors(智能反转颜色)的工作原理。系统会自动反转背景色但保留图片和视频的原始颜色。为了让 Smart Invert 正常工作,需要正确标记装饰性图片和非装饰性图片。

值得深挖的点

UIFontMetrics 解决自定义字体的缩放问题。 过去使用自定义字体的 App 在 Dynamic Type 放大时会”卡住”,因为系统不知道如何缩放自定义字体。UIFontMetrics 允许你指定一个”参照字号”(如 Caption、Body、Title),系统会自动将自定义字体按比例缩放。

Smart Invert 的正确适配。 accessibilityIgnoresInvertColors 属性告诉系统哪些视图不应该被反转。对于照片、视频、App 图标等内容应该设为 true,而对于图标和装饰性背景应该保持 false 让系统反转。

代码片段

// 使用 UIFontMetrics 支持自定义字体的 Dynamic Type
let customFont = UIFont(
    name: "CustomSans-Regular",
    size: 17
)!
// 通过 UIFontMetrics 让自定义字体跟随系统字号变化
let scalableFont = UIFontMetrics(
    forTextStyle: .body  // 以 Body 风格的缩放曲线为参照
).scaledFont(for: customFont)

label.font = scalableFont
label.adjustsFontForContentSizeCategory = true  // 响应运行时字号变化
// 确保 Smart Invert Colors 正常工作
// 对于图片和视频内容,标记为不反转
imageView.accessibilityIgnoresInvertColors = true

// 对于需要保留颜色的自定义图标也是
logoImageView.accessibilityIgnoresInvertColors = true

// 但装饰性背景不需要标记,让系统自动反转
// backgroundImageview.accessibilityIgnoresInvertColors = false  // 默认值
// 不能仅用颜色传达信息——错误示例和正确示例
// 错误:只用红色文字表示错误状态
errorLabel.textColor = .red  // 色盲用户可能无法区分

// 正确:颜色 + 图标
errorLabel.textColor = .systemRed
errorLabel.text = "⚠️ 请输入有效的邮箱地址"

// 检查颜色对比度是否达标
let foregroundColor = UIColor.label
let backgroundColor = UIColor.systemBackground
let contrastRatio = foregroundColor.contrastRatio(with: backgroundColor)
// WCAG AA 要求普通文字对比度 >= 4.5:1

最佳实践

  • 始终用系统颜色(UIColor.label 等)。 系统颜色已经考虑了浅色/深色模式下的对比度,也支持 Smart Invert。
  • 用 UIFontMetrics 包装自定义字体。 只需要一行代码就能让自定义字体支持 Dynamic Type。
  • 色彩信息必须有冗余表达。 永远不要只靠颜色来传达状态,配合图标、文字或形状。
  • 在辅助功能设置中测试极端情况。 把 Dynamic Type 开到最大、开启 Bold Text、开启 Smart Invert,看看布局是否还能正常显示。

还有什么值得关注

  • Xcode 的 Accessibility Inspector 可以检查色彩对比度
  • 新的 UIAccessibility.isBoldTextEnabled 和 isDarkerSystemColorsEnabled 可以检测用户设置
  • 深色模式下的对比度可能与浅色模式不同,两种模式都需要测试
  • SwiftUI 的 .font(.body) 自动支持 Dynamic Type,不需要额外处理
WWDC 2020