草庐IT

ios - UIAccessibilityLayoutChangedNotification 和 UIAccessibilityScreenChangedNotification 之间的实际区别?

coder 2023-07-24 原文

我试图确定发布 UIAccessibilityLayoutChangedNotification 时究竟发生了什么不同, 和 UIAccessibilityScreenChangedNotification .据我所知,我可以在任何地方互换使用它们,没有什么不同。

Apple 文档只是说使用 LayoutChanged当(例如)一个元素被隐藏或显示时,使用 ScreenChanged如果整个屏幕发生变化,但我对他们在我提供这些信息时做了什么感兴趣,以及在使用其中一个或另一个时我应该看到的不同。

任何人都可以清楚地解释两者之间的实现差异吗?

最佳答案

这两个通知用于 View 上的动态内容,并将这些更改传达给屏幕阅读器用户的 VoiceOver。这两个通知之间几乎没有什么区别,除了它们的默认行为,以及 ScreenChange 通知的愚蠢的小“boop beep”。

在这两种情况下,论证

UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, arg);

表示要读出的字符串或屏幕元素,VoiceOver 会将其焦点转移到该元素上。在发生戏剧性的上下文变化时,重要的是将焦点转移到有意义的地方,或宣布发生了此类变化。从可访问性的角度来看,这两种方法都是可以接受的,但我更喜欢涉及尽可能少的更改的方法。在简单的布局更改的情况下,几乎总是最好只宣布上下文更改,并将焦点留在原处。虽然有时,导致上下文更改的元素被隐藏,然后显然有必要直接画外音以突出显示新内容,因为这种情况下的默认行为是未定义的,或者可能是确定性的,但由一个完全不知道的框架决定关于您的应用程序!

考虑到它们都做完全相同的事情,这两个事件之间的区别在于它们的默认行为。如果您向 UIAccessibilityLayoutChangedNotification 提供 nil就好像你什么也没做。如果你为 UIAccessibilityScreenChangedNotification 提供一个 nil 参数一旦所有 View 层次结构更改和绘图完成,它会将焦点发送到 View 层次结构中标记为可访问性元素的第一个 UIObject。

UIAccessibilityLayoutChangedNotification
UIAccessibilityLayoutChangedNotification 的一个很好的用例示例用于动态表单。您想让用户知道,根据他们在表单中做出的决定,可以使用新选项。例如,如果在表单中选择您是退伍军人,则表单的其他区域可能会弹出以提供更多输入,但这些区域可能已对其他不关心它们的用户隐藏。因此,您可以在用户交互后将重点转移到这些元素上:
UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, firstNewFormElement);

这会将焦点转移到提供的元素上,并宣布它是可访问性标签。

或者只是告诉他们新的表单元素在那里:
UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, @"Veterans form elements available");

这会将焦点留在原处,但 VoiceOver 会宣布“退伍军人表单元素可用”。

注意:此特定行为在我的 iPad (8.1.2) 上被窃听。

或者最后你可以这样做:
UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, nil);

这绝对没有任何作用:)。说真的,我什至不认为 a11y 框架后端在乎。这行代码完全是浪费!

UIAccessibilityScreenChangedNotification
UIAccessibilityScreenChangedNotification 的一个很好的用例示例是定制的标签式浏览情况。当整个屏幕(导航区域除外)发生变化时。您想让画外音知道基本上整个屏幕都发生了变化,但不是聚焦第一个元素(您的第一个选项卡)而是聚焦第一个内容元素。
UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, firstNonGlobalNavElement);

它将播放“boop beep”声音,然后将焦点转移到全局导航栏下方。或者你可以这样做:
UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, @"You're on a new tab");

这将等待新标签加载,播放“哔哔”声,在画外音中宣布“你在新标签上”,然后将焦点转移到屏幕上的第一个元素,然后宣布该元素的可访问性标签。 (PHEW!太多了!这对屏幕阅读器用户来说很刺耳。避免这种情况,除非绝对必要)。

最后你当然可以这样做:
UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, nil);    

这相当于:
UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, firstA11yElement);

两者都会播放“哔哔”声,将 VoiceOver 焦点移到屏幕上的第一个元素,然后宣布它。

最后

在评论中有人提到了缓存,我偶尔会在我的回答中评论 A11y 后端可能关心或不关心的事情。虽然肯定有可能发生一些后端魔术,但我不相信这两种情况中的任何一种,后端根本不在乎。我之所以这么说是因为:

如果您曾经使用过 UIAccessibilityContainer协议(protocol),你可以观察你的 View 容器被查询。没有缓存正在进行。甚至 accessibilityElementCount每次 VoiceOver 将焦点更改为容器内的新 AccessibilityElement 时,都会 ping 属性。然后它经历检查它在哪个元素上的过程,请求下一个元素,等等。它的核心设计是为了处理动态情况。如果您在交互后将一个新元素插入到您的容器中,它仍然会通过所有这些查询并且很好!此外,如果您覆盖 UIAccessibility 协议(protocol)的属性,为了提供动态提示和标签,您还可以看到这些函数每次都被调用!因此,我相信 A11y 框架后端从这些通知中收集到的信息绝对为零。 VoiceOver 需要完成它的工作的唯一信息是它当前的焦点辅助功能元素,而这个元素是辅助功能容器。通知只是为了让您的应用程序更适合 VoiceOver 用户使用。

想象一下,如果不是这种情况,Safari 会发布这些通知多少次!!!! :)

这些特定的陈述只能由具有框架后端知识、使用代码的人证实,并且应该被视为猜想。这可能是高度依赖于版本/实现的情况。绝对可以讨论这些要点!这篇文章的其余部分非常具体。

供您引用

其中大部分来自使用框架的经验,但如果您想进一步挖掘,这里有一个有用的引用。

https://developer.apple.com/documentation/uikit/accessibility/uiaccessibility

https://developer.apple.com/documentation/uikit/uiaccessibilitylayoutchangednotification

https://developer.apple.com/documentation/uikit/uiaccessibilityscreenchangednotification

最后,我放在一起测试所有这些东西的愚蠢的小应用程序的开源存储库。

https://github.com/chriscm2006/IOS-A11y-Api-Test

关于ios - UIAccessibilityLayoutChangedNotification 和 UIAccessibilityScreenChangedNotification 之间的实际区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27797515/

有关ios - UIAccessibilityLayoutChangedNotification 和 UIAccessibilityScreenChangedNotification 之间的实际区别?的更多相关文章

随机推荐