简体   繁体   中英

swift-ios- Accessibility - change Voiceover read/focus order to content view first then the navigation items?

I am designing an app with accessibility enabled. I have a rightBarButtonItem on the navigationBar , several labels in between and a button located at the bottom.

I want to achieve the following behaviour: Every time the current view is loaded, the VoiceOver focus will:

  1. start from the topmost label
  2. visit all labels from top to bottom
  3. then, the bottom button
  4. finally, rightBarButtonItem

To ensure such order, I coded in the viewController

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

It did ensure the read order but the focus order failed at the rightBarButtonItem. It couldn't be clicked.

How to solve this problem?

Every time your current view is loaded, use the UIAccessibilityPostNotification method to get your purpose.

There are several types of change notifications but UIAccessibilityScreenChangedNotification may be the one you're interested in.

It notifies that the whole page has changed including nil or a UIObject as incoming parameters :

  • With nil , the first accessible element in the page is focused.
  • With a UIObject , focus is shifted to the specified element .

This notification comes along with a vocalization including a sound like announcing a new page.


EDIT

I misunderstood your problem that is pretty much complicated than I thought.

If you want to have an impact on the navigation bar items, you should make the native ones inaccessible and create your own custom elements to order and/or add custom actions for instance.

Let's take your example with a label, a button and a navigation bar including a right bar button (I don't take into account a potential back button ).

Follow the steps hereunder in your view controller :

STEP 1 : create your outlets.

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

STEP 2 : hide your navigation bar items so as not to listen to their vocalization.

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    self.navigationController!.navigationBar.accessibilityElementsHidden = true
}

STEP 3 : create an accessible element for the right bar button.

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]
}

The last step consists in adding a single action or more to your right bar button according to your application purpose.

Once done, you can customize with this approach and read/focus order to content view first then the navigation items as stated in your question.

This solution may be optimized but it allows to reach your goal.

You can add a function as an UIAccessibility extension to set the focus on any item when you load the screen, then execute your accessibilityElements

extension UIAccessibility {

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM