swift ios-辅助功能-将Voiceover读取/聚焦顺序更改为内容视图,然后再更改导航项目



我正在设计一个启用辅助功能的应用程序。我有navigationBar上的一个rightBarButtonItem,中间有几个标签以及位于底部的按钮。

我希望实现以下行为:每次加载当前视图时,VoiceOver焦点将:

  1. 从最上面的标签开始
  2. 从上到下访问所有标签
  3. 然后,底部按钮
  4. 最后,右BarButtonItem

为了确保这样的顺序,我在viewController中进行了编码

navigationController?.view.accessibilityElements = [label1, label2, button, navigationItem.rightBarButtonItem]

它确实确保了读取顺序,但焦点顺序在右侧BarButtonItem失败。无法单击它。

如何解决这个问题?

每次加载当前视图时,都要使用UIAccessibilityPostNotification方法来获得目的。

有几种类型的更改通知,但UIAccessibilityScreenChangedNotification可能是您感兴趣的通知。

它通知整个页面已经改变,包括nilUIObject作为传入参数:

  • 使用nil,页面中第一个可访问的元素将成为焦点
  • 对于UIObject焦点转移到指定元素

此通知附带一个声音,包括一个类似于宣布新页面的声音。


编辑

我误解了你的问题,这个问题比我想象的要复杂得多。

如果你想对导航栏项目产生影响,你应该让原生项目不可访问,并创建自己的自定义元素来排序和/或添加自定义操作。

让我们以一个标签、一个按钮和一个导航栏为例,其中包括一个右栏按钮(我不考虑潜在的后退按钮(。

在您的视图控制器中执行以下步骤:

第1步:创建您的销售渠道。

@IBOutlet weak var myLabel: UILabel!
@IBOutlet weak var myButton: UIButton!
@IBOutlet weak var myRightBarItem: UIBarButtonItem!

步骤2:隐藏导航栏项目,以免听到它们的声音。

override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationController!.navigationBar.accessibilityElementsHidden = true
}

步骤3:为右栏按钮创建一个可访问的元素。

override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let rightButtonView = myRightBarItem.value(forKey: "view") as? UIView
let navigationBarView = rightButtonView?.superview?.superview?.superview
let newElt = UIAccessibilityElement(accessibilityContainer: self.view)
newElt.accessibilityFrameInContainerSpace = navigationBarView!.convert((rightButtonView?.superview!.frame)!,
      to:self.view)
newElt.accessibilityLabel = "new navigation right bar button"
newElt.accessibilityTraits = .button
//Order your elements as you wish.
self.view.accessibilityElements = [myLabel,
myButton,
newElt]
}

最后一步是根据您的应用程序目的,在右栏按钮上添加一个或多个操作。

完成后,您可以使用此方法进行自定义,并按照问题中所述的顺序读取/聚焦内容,然后查看导航项目。

此解决方案可能经过优化,但可以达到您的目标。

您可以添加一个函数作为UIAccessibility扩展,在加载屏幕时将焦点设置在任何项目上,然后执行accessibilityElements

extension UIAccessibility {
static func setFocusTo(_ object: Any?) {
if UIAccessibility.isVoiceOverRunning {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.8) {
UIAccessibility.post(notification: .layoutChanged, argument: object)
}
}
}

相关内容

最新更新