Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessibility set focus to navigation bar title item

Overview:

I would like to set the accessibility focus to the navigation bar's title item.

By default the focus is set from top left, meaning the back button would be on focus.

I would like the title item to be in focus.

Attempts made so far:

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

Problem:

  • The above code makes no difference, the back button is still in focus.

Possible Cause:

  • Not able to get the item corresponding to the title to be able to set the focus.
like image 804
user1046037 Avatar asked Jun 15 '18 04:06

user1046037


1 Answers

Solution 1 I don't like it, but it was the minimum amount of hacking that does not rely on digging through hidden subviews (internal implementation of UINavigationBar view hierarchy).

First in viewWillAppear, I store a backup reference of the back button item, and then remove the back button item (leftBarButtonItem):

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

    backButtonBackup = self.navigationItem.leftBarButtonItem
    self.navigationItem.leftBarButtonItem = nil  
}

Then I restore the back item, but only after I dispatch the screen changed event in 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
    }
}

Solution 2: Disable all accessibility on the nav bar and view controller up until viewDidAppear() is finished:

    self.navigationController.navigationBar.accessibilityElementsHidden = true
    self.view.accessibilityElementsHidden = true

, and then in viewDidAppear manually dispatching the layout element accessibility focused event to the label subview of 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... 

I'm not a fan of this method either.

DispatchAsync delay in viewDidAppear seems to be needed in any case - and I think both solutions are still horrible.

like image 112
FranticRock Avatar answered Oct 28 '22 17:10

FranticRock