49

Is there a way to set the accessibility focus programatically (App Store safe)? Any help will be greatly appreciated.

Adil Hussain
  • 30,049
  • 21
  • 112
  • 147
John S
  • 1,687
  • 6
  • 21
  • 28

4 Answers4

69

To focus on element you can call.

Swift:

UIAccessibility.post(notification: .screenChanged, argument: self.myFirstView)

ObjC:

UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, self.myFirstView);

Otherwise for iOS 8+ use the accessibilityElements to set element order and it will focus automatically on first element in the list

self.accessibilityElements = @[myFirstView, mySecondButton, myThirdLabel]
Vlad
  • 5,727
  • 3
  • 38
  • 59
  • 14
    There is also `UIAccessibilityLayoutChangedNotification` if the screen didn't change but some view appeared/disappeared in the current screen – Jordan H Jan 07 '18 at 19:46
11
extension UIAccessibility {
    static func setFocusTo(_ object: Any?) {
        if UIAccessibility.isVoiceOverRunning {
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.8) {
                UIAccessibility.post(notification: .layoutChanged, argument: object)
            }
        }
    }
}

Add this extension and call it by passing in the view you would like to be focused. If you would like to change focus when navigating using a tabbar, you can call this from viewWillAppear. This code wont work in any init method without a the delay of 0.7 or more.

2

This is the Swift code:

UIAccessibility.post(notification: .screenChanged, argument: <theView>)

Example usage

let titleLabel = UILabel()

override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        UIAccessibility.post(notification: .screenChanged, argument: titleLabel)
}
vberihuete
  • 174
  • 5
  • I found this often causes the default UIView to be read first and then that gets interrupted with this titleLabel being read. Tried in viewDidLoad and viewWillAppear but that got ignored. Any workarounds for this issue? – Charlie S Jul 03 '21 at 13:53
0
UIAccessibility.post(notification: .layoutChanged, argument: toast)
toast.becomeFirstResponder()
toast.isAccessibilityElement = true
toast.accessibilityTraits = .staticText //Traits option ie .header, .button etc
toast.accessibilityLabel = "Accessibility label to be read by VoiceOver goes here"

WHERE:

  • toast is my UIView (a pop up which gets triggered upon particular scenario)
  • above code needs to be added to the toast View
  • this code will automatically change focus to pop up view (toast) and VoiceOver will read accessibilityLabel
marika.daboja
  • 881
  • 13
  • 27