Reputation:
I need to respond to a single tap and double tap with different actions, but is SwiftUI the double tap gesture is interpreted as two single taps.
In swift you can use fail gesture, but no idea how to do it in SwiftUI.
Example:
.onTapGesture(count: 1) {
print("Single Tap!")
}
.onTapGesture(count: 2) {
print("Double Tap!")
}
TIA.
Upvotes: 29
Views: 9255
Reputation: 1034
Text("Tap Me!").gesture(
TapGesture(count: 2)
.onEnded({ print("Tapped Twice!")})
.exclusively(before:
TapGesture()
.onEnded({print("Tapped Once!") })
)
)
Upvotes: 3
Reputation: 1
I had some problems as well when having 2 or 3 clicks, sometimes the row reacted and sometimes not. Solution, if there is nothing else to be clicked or handled in the row:
.contentShape(Rectangle())
then the onTapGesture works every time!
Upvotes: 0
Reputation: 2242
I had a need for double and triple taps to be recognised on an object but only trigger one of the action closures. I found that the exclusively()
API didn't work for me on iOS 15. So, I created this little hack that does what I want.
Struct ContentView: View {
@State private var isTripleTap = false
var body: some View {
Text("Button")
.gesture(
TapGesture(count: 2).onEnded {
Task {
try? await Task.sleep(nanoseconds: 200_000_000)
if !isTripleTap {
print("Double Tap")
}
isTripleTap = false
}
}
.simultaneously(
with: TapGesture(count: 3).onEnded {
isTripleTap = true
print("Triple Tap")
}
)
)
}
}
Upvotes: 0
Reputation: 481
This can be achieved with exclusively(before:)
. It allows for only one gesture to succeed.
.gesture(
TapGesture(count: 2).onEnded {
print("DOUBLE TAP")
}.exclusively(before: TapGesture(count: 1).onEnded {
print("SINGLE TAP")
})
)
Link to method documentation https://developer.apple.com/documentation/swiftui/gesture/exclusively(before:)
Upvotes: 15
Reputation: 47
There does not seem to be a simple solution (yet), most of these answers trigger both actions. The workaround I have discovered feels clumsy, but works smoothly:
struct hwsView: View {
var body: some View {
VStack {
Text("HWS")
.onTapGesture {
print("Text single tapped")
}
}
.highPriorityGesture(
TapGesture(count: 2)
.onEnded { _ in
print("hws double tapped")
}
)
}
}
Upvotes: 1
Reputation: 112
You can also setup a count for TapGesture like so:
.simultaneousGesture(TapGesture(count: 2).onEnded {
// double tap logic
})
Per Apple Developer Documentation: https://developer.apple.com/documentation/swiftui/tapgesture
Upvotes: -1
Reputation: 119108
First one prevent second one to perform. So reverse the order of your code:
.onTapGesture(count: 2) {
print("Double Tap!")
}
.onTapGesture(count: 1) {
print("Single Tap!")
}
Since the above method reported not working in some situationis, you can try using gesture
s modifier instead:
.gesture(TapGesture(count: 2).onEnded {
print("double clicked")
})
.simultaneousGesture(TapGesture().onEnded {
print("single clicked")
})
Upvotes: 35