文/ 张赐荣
一、简介
VoiceOver 是 iOS 内置的读屏软件,视障用户通过开启旁白,使用触摸或特定手势来操作设备。 双指来回滑动 (俗称“搓擦”或“Z形滑动”)是一个全局性的“退出”手势,类似于操作可见界面中的“关闭”按钮或返回上一级按钮。 典型场景:
• 关闭模态弹窗(如自定义提示框、广告浮层)
• 返回上一级页面(导航栈返回)
• 收起键盘或下拉菜单
• 退出任何需要“取消”的临时状态
当 App 未正确适配时,用户做出此手势只会听到“Ding”提示音,操作被迫中断。
二、实现核心方法 accessibilityPerformEscape
系统通过响应者链查找实现了 accessibilityPerformEscape 并返回 true 的对象。任何继承自 UIResponder 的类均可重写该方法。
1. 在视图控制器中实现(关闭当前页)
// Swift
override func accessibilityPerformEscape() -> Bool {
dismiss(animated:
true, completion: nil) // 关闭模态视图
// 或 navigationController?.popViewController(animated: true)
return true // 必须返回 true,表示手势已处理
}
2. 在自定义视图中实现(关闭局部浮层)
class CustomPopupView: UIView {
override func accessibilityPerformEscape() -> Bool {
removeFromSuperview()
return true
}
}
3. 响应者链传递规则
• VoiceOver 焦点所在的元素会优先处理手势。
• 若焦点元素返回 false ,手势将沿着响应者链向上传递: 视图 → 视图控制器 → 窗口 → UIApplication → AppDelegate 。
• 只要任一对象返回 true ,手势即被认定为有效。
三、最佳实践
1. 返回值必须明确
• 成功处理 → return true
• 未处理(如当前状态无需退出)→ return false ,让系统继续传递或播放提示音。
2. 系统组件自动支持
• UIAlertController 、 UIActivityViewController 、 UIPopoverPresentationController 等系统原生弹窗 无需额外适配
即可响应双指搓擦。
• 不要在这些组件上重复实现,会导致冲突。
3. 避免重复处理
若界面同时存在多个可退出的层级(如浮层上再弹浮层),应确保只有当前焦点的元素处理手势。系统响应者链已处理优先级,通常无需干预。
4. 与可见关闭按钮保持一致
确保 accessibilityPerformEscape 触发的逻辑与界面上的“关闭”、“返回”按钮完全相同,避免状态不一致。
5. 测试验证
• 开启 VoiceOver: 设置 → 辅助功能 → VoiceOver
• 在目标界面 双指来回滑动两次(画“Z”字或快速搓动)
• 预期:界面关闭或执行退出动作;若无效,检查方法是否被调用或返回值是否为 true 。
实际上,适配 VoiceOver 双指来回滑动退出手势,本质就是 为当前界面提供一个标准的无障碍退出方法 。只需在合适的响应者对象中重写 accessibilityPerformEscape 并返回 true ,即可使无障碍体验提升一大步,例如弹窗广告/浮层,推荐尽可能实现该手势。