SwiftUI Slider using VoiceOver not interpreting double tap
I am using SwiftUI to build a Slider
element, and attempting to use a double tap gesture to set its value back to the default. This works fine in non-VoiceOver mode.
According to apple (here), in VoiceOver, a double-tap is done using a triple-tap. (See the Take action on an item
section). However, when I select the Slider in VoiceOver mode, and triple tap, I get the three tones that mean "nothing happened", and my callback is not triggered.
My code is below:
import SwiftUI
struct ContentView: View {
@State var value: Float = 0.5
var body: some View {
VStack {
Slider(value: self.$value, in: 0...1)
.contentShape(Rectangle())
.border(Color.red)
.onTapGesture(count: 2, perform: {
print ("Setting to default!")
self.value = 0.5
})
}
}
}
I've tried adding accessibility traits (at least, the ones that could potentially make sense to me, like allowsDirectInteraction
), and nothing seems to enable this - am I missing something?
Solution 1:
"...when I select the Slider in VoiceOver mode, and triple tap, I get the three tones that mean "nothing happened"...
If no action is defined on the selected item for a specific gesture, VoiceOver
will beep you that "nothing happened", that's normal. 😉
"...and my callback is not triggered."
The gesture recognizer is great but it's only designed for UI, not for VoiceOver
.⚠️
When you touch the screen with VoiceOver
ON, the screen reader analyzes the gesture and makes a kind of mapping with the corresponding actions.
It looks like a layout above your UI that reads your gestures with its definitions, that's why the gesture recognizer doesn't work in this case... whatever 2, 3 or more taps on the screen: nothing is detected because not interpreted as a UI interaction.🤓
To reach this goal, your idea to insert the trait .allowsDirectInteraction
for the slider is great👍.
To work as such, you must activate the direct touch
thanks to the rotor and then touch directly the item it belongs (the slider in your case: beware, touching the thumb has no effect, only the track is good for this element, I don't know why 🤯) ⟹ if you touch outside the item frame, it won't be detected. ⚠️
For your record, this trait creates an area within the frame of the element in which VoiceOer won't make its mapping, only the common UI gesture is known that's why the recognizer works in this case.
At the present time (iOS 15), it's possible to create one's own accessiblity element and define its action when it's activated by implementing its accessibilityActivate dedicated function that will be triggered when a one finger double-tap occurs.
However, the triple tap with one finger that you mention can't be defined nor overriden as far as I know: it may be available only for the Apple items with their own actions (black box forbidden for developpers 🙄).