1

I've built a streaming audio app that looks like this:

enter image description here

When the stream is lost, I overlay this screen:

enter image description here

My issue is that with Voiceover ON, all the underlying controls are still active: I can swipe to them all, and adjust their value.

Here is a snippet of my code for when the signal is lost and regained:

@objc func lostStream() {
    DispatchQueue.main.async {
        self.lossOfSignalBlocker.alpha = 0.0
        self.lossOfSignalBlocker.frame = self.view.bounds
        self.view.addSubview(self.lossOfSignalBlocker)
        self.lossOfSignalBlocker.isUserInteractionEnabled = true
        //UIView.animate(withDuration: 0.2) { self.lossOfSignalBlocker.alpha = 1.0 }
        UIView.animate( withDuration: 0.2, animations: { self.lossOfSignalBlocker.alpha = 1.0 } )

        //Announce loss of signal to Voiceover user.
        UIAccessibilityPostNotification(
            UIAccessibilityAnnouncementNotification,
            "Signal Lost" as NSString
        )
    }
}

@objc func regainedStream() {
    DispatchQueue.main.async {
        UIView.animate( withDuration: 0.2, animations: { self.lossOfSignalBlocker.alpha = 0.0 } )
        { _ in
            self.lossOfSignalBlocker.removeFromSuperview()
        }
    }
}

How do I disable the main UI so that only the overlay responds to any Voiceover-related actions?

Manelion
  • 167
  • 9

2 Answers2

1

On UIAccessibility elements (eg. a view), there is a property called accessibilityElementsHidden. Setting this value to true should hide views that are covered by the arrival of a the "reconnecting" view.

Considering setting the this value to true on the UITableView when in the background.

For more details check out the documentation: https://developer.apple.com/documentation/objectivec/nsobject/1615080-accessibilityelementshidden

Sam
  • 649
  • 5
  • 13
  • Thanks! I set this property, and can still swipe to other tableView UI elements, unless I tap the screen, at which point the highlighting and access to the underlying controls on the main UI goes away. Similarly, when the signal is regained and the overlay dismissed, Voiceover still speaks the overlay text I've set up until I tap the screen again to bring focus back to the main UI. How can I shift focus to different views without additional screen taps? – Manelion Mar 01 '18 at 14:50
1

OK! I've made it work. In addition to setting 'accessibilityElementsHidden' to TRUE, you have to tell the app that the screen has changed by calling 'UIAccessibilityPostNotification' with the 'UIAccessibilityScreenChangedNotification' notification.

Here's what that code looks like now:

@objc func lostStream() {
    DispatchQueue.main.async {

        self.lossOfSignalBlocker.alpha = 0.0
        self.lossOfSignalBlocker.frame = self.view.bounds
        self.view.addSubview(self.lossOfSignalBlocker)
        self.lossOfSignalBlocker.isUserInteractionEnabled = true
        UIView.animate( withDuration: 0.1, animations: { self.lossOfSignalBlocker.alpha = 1.0 } )

        //Disable Voiceover accessibility controls in main view
        self.tableView.accessibilityElementsHidden = true

        //Notify app the screen has changed.
        UIAccessibilityPostNotification(
            UIAccessibilityScreenChangedNotification,
            nil
        )

        //Announce loss of signal to Voiceover user.
        UIAccessibilityPostNotification(
            UIAccessibilityAnnouncementNotification,
            "Signal Lost. Reconnecting." as NSString
        )

    }
}

@objc func regainedStream() {
    DispatchQueue.main.async {

        UIView.animate( withDuration: 0.2, animations: { self.lossOfSignalBlocker.alpha = 0.0 } )
        { _ in
            self.lossOfSignalBlocker.removeFromSuperview()
        }

        //Re-enable Voiceover accessibility controls in main view
        self.tableView.accessibilityElementsHidden = false

        //Notify app the screen has changed.
        UIAccessibilityPostNotification(
            UIAccessibilityScreenChangedNotification,
            nil
        )

        //Announce signal regained to Voiceover user.
        UIAccessibilityPostNotification(
            UIAccessibilityAnnouncementNotification,
            "Reconnected." as NSString
        )

    }
}
Manelion
  • 167
  • 9