辅助功能将焦点设置到导航栏标题项
Accessibility set focus to navigation bar title item
概览:
我想将辅助功能焦点设置到导航栏的标题项。
默认情况下,焦点设置在左上角,这意味着后退按钮将处于焦点上。
我希望标题项目成为焦点。
目前的尝试次数:
UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification,
navigationController?.navigationBar.items?.last)
问题:
- 以上代码没有区别,后退按钮仍然处于焦点状态。
可能的原因:
- 无法获取与标题对应的项目才能设置焦点。
解决方案 1
我不喜欢它,但这是不依赖于挖掘隐藏子视图(UINavigationBar 视图层次结构的内部实现)的最少黑客攻击量。
首先在 viewWillAppear 中,我存储了后退按钮项的备份引用,
然后删除后退按钮项 (leftBarButtonItem):
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
backButtonBackup = self.navigationItem.leftBarButtonItem
self.navigationItem.leftBarButtonItem = nil
}
然后我恢复后面的项目,但只有在我在 viewDidAppear() 中发送屏幕更改事件之后:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, nil)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { [weak self] in
self?.navigationItem.leftBarButtonItem = self?.backButtonBackup
}
}
方案二:
禁用导航栏和视图控制器上的所有可访问性,直到 viewDidAppear() 完成:
self.navigationController.navigationBar.accessibilityElementsHidden = true
self.view.accessibilityElementsHidden = true
,然后在 viewDidAppear 中手动调度布局元素可访问性聚焦事件到 UINavigationBar 的标签子视图:
UIAccessibilityPostNotification( UIAccessibilityLayoutChangedNotification, self.navigationController.navigationBar.subviews[2].subviews[1])
// The label buried inside the nav bar. Not tested on all iOS versions.
// Alternately you can go digging for the label by checking class types.
// Then use DispatchAsync, to re-enable accessibility on the view and nav bar again...
我也不喜欢这种方法。
在任何情况下似乎都需要 viewDidAppear 中的 DispatchAsync 延迟 - 我认为这两种解决方案仍然很糟糕。
首先,我们需要创建一个有用的扩展:
extension UIViewController {
func setAccessibilityFocus(in view: UIView) {
UIAccessibility.post(notification: .screenChanged, argument: view)
}
}
然后,我们就可以像这样将焦点设置在导航栏标题中:
setAccessibilityFocus(in: self.navigationController!.navigationBar.subviews[2].subviews[1])
概览:
我想将辅助功能焦点设置到导航栏的标题项。
默认情况下,焦点设置在左上角,这意味着后退按钮将处于焦点上。
我希望标题项目成为焦点。
目前的尝试次数:
UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification,
navigationController?.navigationBar.items?.last)
问题:
- 以上代码没有区别,后退按钮仍然处于焦点状态。
可能的原因:
- 无法获取与标题对应的项目才能设置焦点。
解决方案 1 我不喜欢它,但这是不依赖于挖掘隐藏子视图(UINavigationBar 视图层次结构的内部实现)的最少黑客攻击量。
首先在 viewWillAppear 中,我存储了后退按钮项的备份引用, 然后删除后退按钮项 (leftBarButtonItem):
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
backButtonBackup = self.navigationItem.leftBarButtonItem
self.navigationItem.leftBarButtonItem = nil
}
然后我恢复后面的项目,但只有在我在 viewDidAppear() 中发送屏幕更改事件之后:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, nil)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { [weak self] in
self?.navigationItem.leftBarButtonItem = self?.backButtonBackup
}
}
方案二: 禁用导航栏和视图控制器上的所有可访问性,直到 viewDidAppear() 完成:
self.navigationController.navigationBar.accessibilityElementsHidden = true
self.view.accessibilityElementsHidden = true
,然后在 viewDidAppear 中手动调度布局元素可访问性聚焦事件到 UINavigationBar 的标签子视图:
UIAccessibilityPostNotification( UIAccessibilityLayoutChangedNotification, self.navigationController.navigationBar.subviews[2].subviews[1])
// The label buried inside the nav bar. Not tested on all iOS versions.
// Alternately you can go digging for the label by checking class types.
// Then use DispatchAsync, to re-enable accessibility on the view and nav bar again...
我也不喜欢这种方法。
在任何情况下似乎都需要 viewDidAppear 中的 DispatchAsync 延迟 - 我认为这两种解决方案仍然很糟糕。
首先,我们需要创建一个有用的扩展:
extension UIViewController {
func setAccessibilityFocus(in view: UIView) {
UIAccessibility.post(notification: .screenChanged, argument: view)
}
}
然后,我们就可以像这样将焦点设置在导航栏标题中:
setAccessibilityFocus(in: self.navigationController!.navigationBar.subviews[2].subviews[1])