SwiftUI 可访问性内部
Source: Dev.to
请提供您希望翻译的具体文本内容,我将为您翻译成简体中文并保持原有的格式、Markdown 语法以及技术术语不变。谢谢!
可访问性是平行视图树
SwiftUI 构建 两棵树:
- 视觉视图树
- 可访问性树
它们相关——但 并不相同。单个视觉视图可以:
- 暴露多个可访问性元素
- 与兄弟视图合并
- 完全隐藏
- 动态更改角色
理解这一点可以解释大多数“为什么 VoiceOver 没有正确朗读?”的 bug。
SwiftUI 如何创建可访问性元素
默认情况下:
- 大多数控件(
Button、Toggle、TextField)会自动生成可访问性元素。 - 容器(
HStack、VStack、ZStack)通常 不会。
示例
HStack {
Image(systemName: "heart.fill")
Text("Favorites")
}
VoiceOver 可能会朗读为:“heart fill, Favorites”,除非你另行指示 SwiftUI。
分组 vs 分离元素
SwiftUI 为您提供对分组的显式控制。
将子元素合并为一个元素
.accessibilityElement(children: .combine)
结果:“Favorites, button”
完全忽略子元素
.accessibilityElement(children: .ignore)
现在您需要手动定义所有内容。
将子元素分别包含(默认)
.accessibilityElement(children: .contain)
当每个子元素都有其自身含义时使用此方式。
角色、特征与语义
可访问性不仅仅是标签——它是意义。SwiftUI 使用特征来描述行为:
isButtonisHeaderisSelectedisDisabled
示例
Text("Settings")
.accessibilityAddTraits(.isHeader)
现在 VoiceOver 能够理解层级,而不仅仅是文本。
焦点系统(对导航至关重要)
SwiftUI 的可访问性焦点是基于状态驱动的。
@AccessibilityFocusState var focused: Bool
Text("Error occurred")
.accessibilityFocused($focused)
触发焦点:
focused = true
适用于以下情况:
- 表单验证错误
- 导航过渡
- 警报和弹出页
- 动态内容更新
如果没有焦点控制,用户会迷失方向。
状态更改与可访问性更新
SwiftUI 会在以下情况下自动朗读更改:
- 文本更改
- 值更新
- 控件切换
自定义视图需要显式朗读:
UIAccessibility.post(
notification: .announcement,
argument: "Upload complete"
)
请谨慎使用——但要有意图地使用。
可访问性与 NavigationStack
导航会影响可访问性树。导航时:
- 先前的元素被移除
- 构建新的树
- 除非手动控制,否则焦点会重置
导航后最佳实践:
.accessibilityFocused($focusOnTitle)
这与 UIKit 的 “screen changed” 行为相同。
手势 vs 可访问性操作
自定义手势默认不可访问。
不良示例
.onTapGesture { submit() }
VoiceOver 用户无法发现此手势。
正确示例
.accessibilityAction {
submit()
}
或者使用真实的 Button。
隐藏装饰性元素
装饰性视图应对辅助功能隐藏:
Image("background")
.accessibilityHidden(true)
否则 VoiceOver 会朗读无意义的内容。
动态文字是布局问题
动态文字不仅仅是字体——它会影响布局。SwiftUI 会自动:
- 增大字体大小
- 重新排版文本
- 调整行高
您的布局必须允许增长。
不良实践
- 固定高度
- 文本被裁剪
- 僵硬的堆叠
良好实践
- 灵活的框架
- 多行文本
- 自适应布局
正确测试可访问性
- Simulator: VoiceOver, Dynamic Type, Reduce Motion, Increase Contrast
- Xcode Accessibility Inspector: element order, labels, traits, hit targets
经验法则: 如果导航时感觉别扭 → 那可能就是问题所在。
可访问性设计规则(内部级别)
- 可访问性是状态驱动的
- 焦点是显式的
- 语义比标签更重要
- 自定义视图需要自定义可访问性
- 导航会重置焦点,除非进行处理
- 手势需要可访问性操作
- 布局必须支持动态文字大小
最后思考
SwiftUI 可访问性并不是一个后加的功能。它是一个与以下各方面紧密结合的一流系统:
- 渲染
- 状态
- 导航
- 布局
- 交互
当你从一开始就将可访问性纳入设计时:
- 你的 UI 会更清晰
- 你的架构会得到改进
- 你的应用会更具 “Apple 风格”
- 所有人都会受益 —— 不仅仅是使用辅助功能的用户