辅助功能将焦点设置到导航栏标题项

Posted

技术标签:

【中文标题】辅助功能将焦点设置到导航栏标题项【英文标题】:Accessibility set focus to navigation bar title item 【发布时间】:2018-06-15 04:14:51 【问题描述】:

概述:

我想将辅助功能焦点设置到导航栏的标题项。

默认情况下,焦点是从左上角设置的,这意味着后退按钮将成为焦点。

我希望标题项成为焦点。

目前的尝试:

    UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification,
                                    navigationController?.navigationBar.items?.last)

问题:

上面的代码没有区别,返回按钮仍然是焦点。

可能的原因:

无法获取title对应的item来设置焦点。

【问题讨论】:

同样的问题,类似的尝试没有成功: UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, self.navigationController?.navigationBar.topItem) 。还尝试在 viewDidAppear 中添加延迟 - 没有任何区别。 注意到,即使是苹果的应用程序,例如通讯录,也是以返回按钮开头,然后是标题 令人震惊的是,Apple 还没有解决这个问题。 【参考方案1】:

解决方案 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
    

解决方案 2: 禁用导航栏和视图控制器上的所有可访问性,直到 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 延迟 - 我认为这两种解决方案仍然很糟糕。

【讨论】:

实际上我喜欢第二个选项,您是否可以编辑答案以添加 2 个标题(降价)作为“选项 1”和“选项 2”。了解您的答案中有两个选项可能会有所帮助【参考方案2】:

首先,我们需要创建一个有用的扩展:

extension UIViewController 
    func setAccessibilityFocus(in view: UIView) 
        UIAccessibility.post(notification: .screenChanged, argument: view)
    

然后,我们就可以将焦点设置在导航栏标题中,如下所示:

setAccessibilityFocus(in: self.navigationController!.navigationBar.subviews[2].subviews[1])

【讨论】:

以上是关于辅助功能将焦点设置到导航栏标题项的主要内容,如果未能解决你的问题,请参考以下文章

辅助功能 - 如何在元素上设置自定义选项卡焦点顺序

有没有办法在导航栏后退按钮上自定义辅助功能标签?

关于 iOS 辅助功能。如何将焦点转移到pickerView

将辅助功能画外音光标焦点移动到特定元素

iOS - 辅助功能方法 - 移动焦点

将导航栏项目添加到 IB 中的辅助视图