Highlight
Switch Control 是 iOS 内置的辅助功能,允许运动能力受限的用户用外部开关控制屏幕光标;本 session 展示了如何用
accessibilityNavigationStyle、accessibilityElements、焦点回调和UIAccessibilityCustomAction减少扫描等待、自动展示卡片内容,并把双击/长按操作放进顶层菜单。
核心内容
Switch Control 用户常常通过轮椅上的开关、头部点击、舌头点击或吸管呼吸来操作设备。系统会让光标在界面元素之间移动,用户等到目标元素被选中后再触发开关。对于触摸用户来说一次点击就完成的事,对开关用户可能意味着等待、进组、打开菜单,再选择动作。(00:59)
这场 session 把问题放进一个叫 Shape Shuffle 的儿童学习游戏。游戏里有弯曲的关卡路径、需要翻开的卡片,以及频繁使用的双击和长按。触摸用户玩起来很自然,Switch Control 用户会遇到三个障碍:关卡扫描顺序不对,找远处关卡要等很久;每张卡片都要额外操作才看得到内容;双击和长按要反复进入 gestures 子菜单。(05:15)
Apple 给出的思路很直接:先把 App 做到完整支持 VoiceOver,因为许多 accessibility 标注会被 Switch Control 复用;随后针对开关用户补上几处体验 polish。关卡列表用分组和显式顺序减少等待,卡片用焦点回调自动翻开,常用手势用 Custom Actions 放到顶层菜单。(04:22)
收尾部分提醒开发者把运动障碍用户的操作成本纳入产品流程。删除账号、删除全部数据这类高后果操作要确认;验证码和配对码界面在 Switch Control 运行时不应设置短超时;包含账号、医疗等隐私内容的界面要减少长时间暴露。(12:29)
详细内容
控制扫描分组和顺序
(07:49)Shape Shuffle 的关卡沿着弯曲路径排列,但 Switch Control 默认按从上到下、从左到右扫描。开发者可以先把一组关卡合并成一个扫描组,再显式指定组内元素顺序。
containerView.accessibilityNavigationStyle = .combined
containerView.accessibilityElements = [levelFourView, levelFiveView, levelSixView]
关键点:
accessibilityNavigationStyle = .combined让容器内的元素作为一个组合参与扫描,减少顶层元素数量。accessibilityElements覆盖默认几何排序,适合弯曲路径、棋盘、地图和其他视觉顺序不等于阅读顺序的界面。- 这个改动直接解决 level 30 这类远处目标的等待问题,因为用户先进入正确的组,再在组内按设计顺序移动。
让焦点自动展示内容
(08:47)卡片游戏依赖点击来翻面。手动扫描的 Switch Control 用户每移动到一张卡都要额外触发操作,成本会随着卡片数量增长。session 的做法是在卡片获得辅助功能焦点时翻到正面,失去焦点时翻回背面。
class CardView: UIView {
var orientation: CardOrientation
enum CardOrientation {
case front
case back
}
override func accessibilityElementDidBecomeFocused() {
self.flip(to: .front)
}
override func accessibilityElementDidLoseFocus() {
self.flip(to: .back)
}
// 其余 class 内容...
}
关键点:
accessibilityElementDidBecomeFocused()在辅助功能焦点到达卡片时调用。self.flip(to: .front)把原本需要点击才能看到的内容提前展示出来。accessibilityElementDidLoseFocus()让卡片离开焦点后恢复背面,保持游戏规则。- 这个行为可以做成用户设置,因为 transcript 提到自动扫描用户未必需要它,手动扫描用户更受益。
把常用手势放进顶层菜单
(09:15)游戏中的双击用于添加卡片,长按用于 pin 卡片。Switch Control 用户能执行这些手势,但要频繁进入 gestures 子菜单。UIAccessibilityCustomAction 把这些常用操作变成顶层菜单项,减少菜单层级。
func configureActions() {
let pinAction = UIAccessibilityCustomAction(
name: "Pin Card") { (_) -> Bool in
self.setPinned(true)
return true
}
pinAction.image = UIImage(systemName: "pin")
let addAction = UIAccessibilityCustomAction(
name: "Add Card") { (_) -> Bool in
self.setSelected(true)
return true
}
addAction.image = UIImage(systemName: "add.square")
self.accessibilityCustomActions = [addAction, pinAction]
}
关键点:
- 每个
UIAccessibilityCustomAction对应一个用户可触发的行为。 - closure 返回
true表示动作已处理。 accessibilityCustomActions决定当前视图在 Switch Control 菜单里暴露哪些操作。- iOS 14 允许给 custom action 设置
image;session 使用 SF Symbols 做 pin 和 add 图标,未设置图片时菜单显示动作名称首字母。
检测 Switch Control 与静态文本交互
(11:41)session 还点名了两个小 API。一个用于判断 Switch Control 是否正在运行,另一个用于把看起来像静态文本、实际会响应点击的元素纳入 Switch Control 导航。
static var isSwitchControlRunning: Bool { get }
var accessibilityRespondsToUserInteraction: Bool { get set }
关键点:
isSwitchControlRunning适合控制只面向 Switch Control 的体验开关,例如延长验证码页面的超时时间。- transcript 同时提到有对应 notification,适合在状态变化时更新界面。
accessibilityRespondsToUserInteraction适合会响应点击的UILabel一类静态外观元素。- 设置后,Switch Control 会把这类元素当作可导航目标处理,避免用户找不到隐藏交互。
为误触和慢输入留余地
(12:44)运动障碍用户可能有 tremors 或其他非自主动作,误触概率更高。高后果操作要加确认;认证码、配对码页面在 Switch Control 运行时要避免短超时;包含账号、医疗等私密信息的界面要尽快收起敏感内容。
关键点:
- 删除全部数据、退出登录、删除账号等操作要有确认流程。
- 输入更慢和纠错更慢是 autoscanning 的直接结果,安全流程不能只按触摸用户速度设计。
- 设备可能固定在轮椅上,屏幕隐私条件弱于手持设备。
核心启发
开关友好的卡片学习模式
做什么:给记忆卡、语言学习或儿童认知游戏增加 Switch Control 模式,焦点到达卡片时自动揭示内容。
为什么值得做:session 的卡片示例表明,反复点击翻卡会让手动扫描用户疲劳。
怎么开始:在卡片 UIView 上实现 accessibilityElementDidBecomeFocused() 和 accessibilityElementDidLoseFocus(),把翻面逻辑放进焦点生命周期,再提供一个设置项让用户打开自动翻卡。
分组扫描的关卡、棋盘和地图
做什么:为关卡地图、座位图、棋盘或楼层图建立符合任务顺序的扫描分组。
为什么值得做:默认从上到下、从左到右的顺序会破坏弯曲路径和空间布局,用户要等更久才能到达目标。
怎么开始:用容器视图承载一组元素,设置 accessibilityNavigationStyle = .combined,再把 accessibilityElements 排成用户完成任务时真正需要的顺序。
顶层菜单里的高频动作
做什么:把 pin、完成、收藏、加入答案这类高频动作放进 Switch Control 顶层菜单。
为什么值得做:双击、长按和 swipe action 虽然可达,但反复进入 gestures 子菜单会拖慢流程。
怎么开始:为每个行为创建 UIAccessibilityCustomAction,在 closure 里调用现有业务方法,最后赋给当前元素的 accessibilityCustomActions。
无短超时的验证码流程
做什么:让登录、配对和验证码页面在 Switch Control 运行时使用更宽松的时间窗口。
为什么值得做:autoscanning 用户输入更慢,修正错误也更慢,短超时会把辅助功能用户挡在流程外。
怎么开始:读取 isSwitchControlRunning,在该状态下延长倒计时、暂停自动关闭,或提供重新发送前的明确确认。
可交互标签的无障碍暴露
做什么:把外观像文本、实际能点击的统计项、状态标签或小型控制项纳入 Switch Control 导航。
为什么值得做:Switch Control 需要知道它们会响应用户交互,否则用户可能扫不到关键入口。
怎么开始:对这类元素设置 accessibilityRespondsToUserInteraction = true,再补齐 label、traits 和触发后的状态反馈。
关联 Session
- Make your app visually accessible — 从颜色、文字大小、Button Shapes、Smart Invert 等设置检查视觉无障碍基础。
- Create a seamless speech experience in your apps — 讲 AVSpeechSynthesizer、assistive technology announcement 和语音输出时机。
- VoiceOver efficiency with custom rotors — 用 custom rotors 帮 VoiceOver 用户在复杂界面中快速跳到相关内容。
- Accessibility design for Mac Catalyst — 讨论 Mac Catalyst App 的键盘、鼠标、元素分组和 Accessibility Inspector 测试。
- Build for the iPadOS pointer — 继续处理鼠标、触控板和其他间接输入设备带来的交互适配。
评论
GitHub Issues · utterances