Search code examples
iosfocusuipageviewcontrollervoiceoveruiaccessibility

Prevent VoiceOver from focusing on an object automatically


On the home screen, when you swipe with three fingers to navigate the home screens pages, notice how the focused app loses focus upon swipe, the page is changed, VoiceOver announces the new page number, then it force focuses the first app on that page. There's a period of time where nothing is focused. I have a similar interface in my app and I need to do the exact same thing.

Right now I post an announcement to state the page number and then I programmatically change the page, but this announcement doesn't get the chance to finish before VoiceOver automatically focuses an element on the new page and then it announces that label. My announcement is interrupted.

How can I prevent VoiceOver from focusing an element automatically upon switching pages in a UIPageViewController, or otherwise obtain the desired behavior?

EDIT: I see you're supposed to post UIAccessibilityPageScrolledNotification when the page changes and you can provide a string as an argument that VoiceOver will announce to state the new page position. However, there is no way to know when this notification finishes I don't believe, so I cannot force focus once that has finished speaking.


Solution

  • If you want to provide a custom scroll status announcement, implement -accessibilityScrollStatusForScrollView: to provide accessibility clients with a scroll status string. If -accessibilityScroll: is overridden, instead post an UIAccessibilityPageScrolledNotification.

    If you'd like to sequence announcements, register for UIAccessibilityAnnouncementDidFinishNotification and post your screen change notification from within the notification handler. Note the presence of the UIAccessibilityAnnouncementKeyWasSuccessful key in the notification dictionary, too.

    As we discussed in the comments, you experienced issues with UIPageViewController navigation interrupting your announcement even after experimenting with the above methods. It's important to post the UIAccessibilityPageScrolledNotification after the transition completes. The UIPageViewController method that you use to swap pages, setViewControllers:direction:animated:completion:, accepts a completion block. By posting the page scrolled notification from within the completion block, rather than on the next line, you can avoid interruption.