【问题标题】:Add NSAccessibilityElement to an existing NSView将 NSAccessibilityElement 添加到现有的 NSView
【发布时间】:2020-11-13 16:24:17
【问题描述】:

我想将MacOS accessibility feature 与我的应用程序一起使用,该应用程序呈现自己的自定义 UI(即不使用 Cocoa)。为此,我实现了与我绘制的每个小部件相关联的子类NSAccessibilityElements 树。 根 UI 容器托管在外部提供给我的应用程序的 NSView 内(我的应用程序是一个插件)。现在我需要将我的NSAccessibilityElements 树附加到主机提供的现有NSView

Apple documentation 推荐两种方法来实现这一点:

  • 重新实现父级的accessibilityChildren 属性以包含自定义元素(例如Qt 使用此方法)。不幸的是,我自己没有创建父 NSView,它是从外部注入的。
  • 调用accessibilityAddChildElement便捷方法。但是当我在提供的NSView 对象上调用它时,我得到一个异常,它不响应此方法。

NSAccessibilityElements 树附加到现有NSView 的正确方法是什么?

【问题讨论】:

  • 您想要实现哪些无障碍功能?您是否尝试过NSView 上的setAccessibilityX 方法?例如设置视图的角色:setAccessibilityRole(_:)
  • @smr 我可以在提供的NSView 上调用setAccessiblityX 方法,除了accessibilityAddChildElement 一个,这是我追求的一个。

标签: macos cocoa accessibility nsview appkit


【解决方案1】:

所以我最终将NSView 子类化以捕获顶级NSAccessibilityElement。重写的- (NSArray*) accessibilityChildren 方法将捕获的可访问性元素作为其子元素之一返回:

@interface AccessibilityRootView : NSView
- (instancetype)initWithAccessibilityElement: (NSAccessibilityElement*)anElement;
@end

@implementation AccessibilityRootView
{
    NSAccessibilityElement* element;
}

- (instancetype) initWithAccessibilityElement: (NSAccessibilityElement*)anElement
{
    self = [super init];

    if (self)
        element = anElement;

    return self;
}

- (NSArray*) accessibilityChildren
{
    NSArray<NSAccessibilityElement*> *children = [super accessibilityChildren];

    int numKids = (int)[children count] + 1;
    NSMutableArray<NSAccessibilityElement*> *kids = [NSMutableArray<NSAccessibilityElement*> arrayWithCapacity:numKids];

    for (id object in children)
        [kids addObject:object];

    [kids addObject: element];

    return NSAccessibilityUnignoredChildren (kids);
}
@end

然后我将这个大小为零的子类视图附加到主机提供的父 NSView

NSView* hostView = /* host-provided NSView */;
AccessibilityRootView* accessibilityRootView = [[AccessibilityRootView alloc] initWithAccessibilityElement:(NSAccessibilityElement*)topLevelAccessibilityElement];
[hostView addSubview:accessibilityRootView];
[accessibilityRootView release];

此时我所有的NSAccessibilityElements 都附加到主机提供的视图中的零大小视图,MacOS 可以成功查询这些项目。

此外,每个NSAccessibilityElement 都必须正确实施其 - (NSRect)accessibilityFrame- (id) accessibilityHitTest:(NSPoint)point 以匹配我自定义绘制的 UI 小部件的屏幕位置。

【讨论】:

  • 这似乎非常接近我现在想要实现的目标!不过,快速的问题 - 您是在初始化时动态地将元素传播到主机视图还是只传播一次?在大多数情况下,我决定使用NSAccessibilityPostNotificationWithUserInfo,但这并没有更新框架……哦,天哪,让框架工作真是太痛苦了。我正在设置setAccessibilityFrameInParentSpace,但这也没有减少它。我还是不明白为什么accessibilityAddChildElement 会抛出异常,lol...
  • @cieplik 我在构建(或重构)UI 时执行一次。然后,我为每个非本地 UI 元素对等 NSAccessibilityElement。这些实现(NSRect)accessibilityFrame,如我的回答中所述,以正确报告UI元素的位置。我从不调用accessibilityAddChildElementsetAccessibilityFrameInParentSpace,而只实现accessibilityChildrenaccessibilityParent 方法,它们使用我的非本地小部件的层次结构树来确定元素之间的关系。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-22
  • 2011-06-24
相关资源
最近更新 更多