支持 OpenGL 的 UIViews 中的旁白和滚动

VoiceOver and Scrolling in OpenGL backed UIViews

我正在寻找有关如何将使用 OpenGL 绘制的可滚动列表制作成可通过 VoiceOver 访问的 CAEAGLLayer 支持的 UIView 的建议。理想情况下,OpenGL 中的可滚动列表应该表现得像本机 UIScrollView:

  1. 当用户用三个手指滑动 left/right 时,我想滚动 up/down 一页。通过实施 accessibilityScroll: 方法可以轻松实现此行为。
  2. 当用户用一根手指滑动 left/right 以浏览列表中的所有项目并且辅助功能焦点移动到列表的 last/first 部分可见项目时,我希望列表稍微滚动以确保新聚焦的项目完全可见。
  3. 当用户直接点击列表的 last/first 部分可见项目以将辅助功能焦点直接移动到它时,我不希望发生滚动操作。
  4. 当用户在列表的 last/first 部分可见项被选中时用一根手指继续滑动 left/right 时,我希望列表滚动 up/down 一页以显示以前隐藏的项目。

正如我上面所说,我知道如何实现项目 #1,但在广泛研究后 Apple's documentation 我仍然不知道如何使项目 #2 到 #4 与 iOS 一起工作可访问性 API。不过,我确实认为这些项目对于出色的无障碍体验很重要。

非常感谢任何建议。谢谢!

UIAccessibility 是一种非正式协议,它提供辅助功能客户端(例如 VoiceOver)解释和导航用户界面所需的数据。 UIKit 类 实现此协议中的全套方法,默认情况下呈现大多数视图。但是,不直接由 UIView 支持的界面元素,例如包含您的 CAEAGLLayer 的视图,必须 手动 实现所有相关的辅助功能方法。

使此内容可访问的最佳且通常唯一的方法是实施 UIAccessibilityElement objects corresponding to the content of the scene. To do so, you must declare the UIView in the UIKit view hierarchy to be a UIAccessibilityContainer 的影子层次结构。这是一个两步过程。首先,您必须通过将 isAccessibilityElement 设置或覆盖 return false 来确保支持容器的视图本身不是可访问性元素。其次,您必须实施非正式 UIAccessibilityContainer 协议中定义的四种方法来访问子无障碍元素:

  • func accessibilityElementCount()
  • func index(ofAccessibilityElement element: Any)
  • func index(ofAccessibilityElement: Any)
  • var accessibilityElements: [Any]?

在大多数情况下,您需要维护一个 UIAccessibilityElement 对象数组,每个对象代表您自定义呈现的用户界面的一个组件。该数组可用于作为 UIAccessibilityContainer 履行您的支持视图的合同。然后,您可以使用 UIAccessibility 协议中的方法扩展元素,使其表现得像滚动视图、按钮和其他控件。

为了完成 #1,您需要在可访问性层次结构中的一个元素上实现 accessibiilityScroll() 以响应滚动操作,returning true 和 posting a UIAccessibilityPageScrolledNotification 带有描述新滚动位置的字符串参数。听起来这部分工作没有问题。

要求 #2、#3 和 #4 都需要在元素获得焦点时以编程方式滚动视图(或者,在 #3 的情况下,选择不执行任何操作)。这可以使用 UIAccessibilityFocus 非正式协议来完成。特别是,每个元素都可以响应 func accessibilityElementDidBecomeFocused() 并将其焦点状态反馈给负责滚动视图的对象。如果这触发了分页滚动,请不要忘记 post 上面讨论的页面滚动通知。