让你的 App 视觉上更无障碍
Make your app visually accessible
2020年6月23日
一句话判断
视觉无障碍不只是加个 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,不需要额外处理