Direct Touch
When playing this game, users spend most of their time moving the sliders. Although a VoiceOver user can double-tap and hold to activate a slider’s standard action, it would be more convenient if they could move the slider directly.
Continue with your project from the first demo or open the RGBullsEye app in the Demo 2 Starter folder.
In ContentView, right at the bottom, is ColorSlider. The Slider view already has an accessibilityValue. Below this, add another modifier:
.accessibilityDirectTouch(options: .silentOnTouch)
It’s a better user experience if VoiceOver is silent while the user moves the slider. The silentOnTouch option prevents VoiceOver speaking for some controls. Let’s see if it works for sliders.
Build and run the app on your device. Tap a slider to select it, then move it.
Sadly, the silentOnTouch option doesn’t work while the user moves the slider, only when they first touch it. Go back to ColorSlider to replace the accessibility value:
.accessibilityValue(String(""))
This effectively removes the value, so VoiceOver has nothing to say. You must define accessibilityValue, or VoiceOver will fall back to speaking the default “per cent” value of the slider.
Build and run again. Select a slider and move it.
It’s much easier to concentrate on playing the game when VoiceOver isn’t speaking continuous updates!
Tap Hit Me! to refresh your memory of what VoiceOver says:
Activate to dismiss pop-up window, Button.
You must swipe to hear “Congratulations” and the all-important score.
Announcement
In Xcode, open SuccessView.
When the user taps Hit Me!, the app presents SuccessView, which shows the user’s score, the RGB values of the target and user’s guess, and a button to play another game. For most players, the most important information is the score, and it would be helpful for VoiceOver to announce this first.
In SuccessView, create a high-priority announcement as a computed variable:
var scoreAnnouncement: AttributedString {
var scoreString = AttributedString("You scored \(score) points on this color.")
scoreString.accessibilitySpeechAnnouncementPriority = .high
return scoreString
}
The string is the same one that appears in the Text view.
You must use AttributedString here because String doesn’t have an accessibilitySpeechAnnouncementPriority property.
Now, to post this announcement as soon as SuccessView appears, add this modifier to ZStack :
.onAppear {
AccessibilityNotification.Announcement(scoreAnnouncement)
.post()
}
Build and run the app on your device, then tap Hit Me!.
Now, when SuccessView appears, VoiceOver reads out the score.
Swipe right to listen to the combined text.
And another swipe reaches the Try another one? button.
After hearing the score announcement, many users would prefer to bypass the text and go straight to a new game. To streamline the user’s experience even more, increase the priority of Try another one? by adding this modifier to its VStack:
.accessibilitySortPriority(2)
Build and run the app on your device, then tap Hit Me!.
After the score announcement, swipe right to go to Try another one?.
Now, RGBullsEye is a much better experience for VoiceOver users!