问题描述
我正在使用 NSCollectionView
来水平布局自定义视图。每个 NSCollectionViewItem
托管一个自定义 NSView
,其作用类似于复选框。这些自定义子视图本身支持可访问性(通过覆盖所需的可访问性方法,例如 accessibilityRole
、accessibilityLabel
等)。
但是,我似乎无法将这些自定义视图提升为主要 UI 视图,以便可以直接访问它们。当我使用辅助功能检查器进行检查时,每个集合视图项似乎都是一个 Group
,并且似乎无法自动按下按钮,例如,因为自定义视图对其不可见。>
我尝试在集合视图项上实现 NSAccessibilityButton
,但是我不知道为 accessibilityParent()
返回什么 - 默认情况下 NSCollectionViewItem
似乎返回父集合视图部分,但是如果没有子类化 NSCollectionView 及其布局,这是无法访问的。
以下也无济于事:
public override var accessibilityFocusedUIElement: Any? {
return self.customView
}
这永远不会被调用。问题是,如何在使用 NSCollectionView
/ NSCollectionViewItem
时添加对可访问性的支持?我只是希望显示它的一个子视图,以便自动程序或键盘大师等应用程序可以访问它。
解决方法
不确定这是一种解决方法还是唯一可能的解决方案,但这就是我让它工作的方式:
- 创建一个新的无障碍代理类,可以转发无障碍相关的查找
- 将此类设置为 `loadView() 中的
view
的NSCollectionViewItem
- 将调用转发到“可访问的”子视图
这是我的代理类:
import Foundation
import Cocoa
/// A wrapper view that acts as a proxy for re-directing accessibility-related lookups.
/// This can be useful in a `NSCollectionViewItem`,for example,to re-direct requests to a child view you'd like to suface as the main,accessible view.
public class BKProxyAccessibleButton: NSView {
public var isAccessibilityElementProxy: (()->Bool)? = nil
public var accessibilityFocusedUIElementProxy: (()->Any?)? = nil
public var accessibilityPerformPressProxy: (()->Bool)? = nil
public var accessibilityValueProxy: (()->NSNumber?)? = nil
public var accessibilityHelpProxy: (()->String?)? = nil
public var accessibilityLabelProxy: (()->String?)? = nil
}
// MARK:- Accessibility
extension BKProxyAccessibleButton: NSAccessibilityButton {
open override func accessibilityRole() -> NSAccessibility.Role? {
return .button
}
open override func accessibilityHelp() -> String? {
return accessibilityHelpProxy?()
}
open override func accessibilityLabel() -> String? {
return accessibilityLabelProxy?()
}
open override func accessibilityTitle() -> String? {
return accessibilityLabelProxy?()
}
open override func isAccessibilityElement() -> Bool {
return isAccessibilityElementProxy?() ?? false
}
open override var accessibilityFocusedUIElement: Any? {
return accessibilityFocusedUIElementProxy?()
}
open override func accessibilityPerformPress() -> Bool {
return accessibilityPerformPressProxy?() ?? false
}
@objc public override func accessibilityValue() -> Any? {
return accessibilityValueProxy?()
}
}