如何重新排序VoiceOver在NSTableCellView上读取NSTextField的方式?

时间:2017-12-12 22:26:33

标签: swift macos cocoa accessibility voiceover

我有一个单列NSTableView,填充了自定义NSTableCellView,非常类似于macOS的标准邮件应用。每个自定义NSTableCellView都有四个不可选择的只读NSTextField。 VoiceOver for Accessibility从左到右,从上到下读取内容。这导致VoiceOver用户的订单非最佳。

如何更改VoiceOver在每个NSTableCellView中读取NSTextField的顺序?

我看到的关于重新订购VoiceOver元素的所有示例和文档都与iOS有关,但不幸的是,macOS中的API仍然不同。

1 个答案:

答案 0 :(得分:0)

元素的可访问性子元素被访问的顺序可以通过 accessibilityChildrenInNavigationOrder() 控制。一共有三种皱纹:

  1. 子项需要将视图本身报告的内容与其 accessibilityChildren 相匹配。所以对于控件,这将是控件的单元格。
  2. 对其子项进行重新排序的视图必须是 accessibilityElement
  3. 该方法期望将您要访问的所有子项传递给它。如果您遗漏任何内容,它们将不会被访问,并且会在 VoiceOver 中有效隐藏。

因此,如果您有 4 个 VO 正在按 labelClabelBlabelDlabelA 的顺序读取的字段,但您想要不同的顺序,您可以在 Swift 5 中像这样使用它:

let orderedFields = [labelA, labelB, labelC, labelD]
let orderedChildren = orderedFields.compactMap { $0?.cell }

view.setAccessibilityChildrenInNavigationOrder(orderedChildren)
view.setAccessibilityElement(true)

对于有很多孩子的视图,这很快变得笨拙,但在您的情况下它应该有效。如果您想动态执行此操作,并且您的所有子项都是带有单元格的 NSControl,则可以使用 NSCelltag 属性对单元格进行排序:

let children = view.accessibilityChildren() as! [NSCell]
let orderedChildren = children.sorted { $0.tag < $1.tag }
        
view.setAccessibilityChildrenInNavigationOrder(orderedChildren as [NSAccessibilityElementProtocol])
view.setAccessibilityElement(true)

然后只需在界面生成器中设置单元格标签即可。