Search code examples
iosvoiceoveruiaccessibility

Views outside superview bounds are inaccessible to VoiceOver when panning around


In my app, I have some controls that are subviews of a UIView but their frames are outside the superview bounds. They are visible to sighted users because clipsToBounds is false. For VoiceOver users, they can highlight a control that is within its superview bounds then swipe right to highlight the next control which is outside the bounds. That works as expected. But if they instead tapped down and panned around the screen, VoiceOver never highlights the elements outside its superview bounds. How can I ensure those elements will be accessible when panning around?

I've created an example project that experiences this issue. Here there are two buttons added as subviews to a gray UIView. Button 0 is located within the bounds of its superview, Button 1 is located outside. Button 0 is accessible when panning around, Button 1 is not.

enter image description here


Solution

  • It appears as though the accessibility framework uses UIView.point(inside:_, with:_) to determine whether or not a view is accessible via VoiceOver.

    I've solved this problem by overriding this function on the superview and returning true when the point is outside of the superview's bounds but inside the subview's bounds.

    In this particular case, my superview has a background view that's drawn outside of the superview's bounds, and the view I wanted to be accessible to VoiceOver is inside of that background view's bounds. So I have:

    override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
        return background.frame.contains(point)
    }
    

    Adjust as appropriate for your scenario.