
Responding to gestures: Tapping
Discover how to respond to tap gestures and get the location of the tap in a SwiftUI app
One of the standard gestures a user can use to interact with the user interface of an app or objects within the app is the tap gesture. In SwiftUI, to allow a view to react to a tap gesture, use the onTapGesture(count:perform:)
modifier.
import SwiftUI
struct ContentView: View {
@State private var circleColor: Color = .orange
var body: some View {
VStack {
Circle()
.fill(circleColor)
.frame(width: 250, height: 250)
.onTapGesture {
circleColor = .blue
}
}
}
}
The modifier adds an action to be performed when the view recognizes the tap gesture. In the example above, when the user taps on the Circle
view, it calls the code block associated with the gesture.
Using the count
parameter, you can also define the number of taps required to trigger the action.
In the example below, by initializing the tap gesture with a count value of two, the action will be performed after two consecutive taps.
struct ContentView: View {
@State private var circleColor: Color = .orange
var body: some View {
VStack {
Circle()
.fill(circleColor)
.frame(width: 250, height: 250)
.onTapGesture(count: 2) {
circleColor = .blue
}
}
}
}
Customizing the gesture
For further customization, you can define the tap gesture as a separate object and then associate it with the view using one of the variations of the gesture(_:)
modifier.
gesture(_:isEnabled:)
: Defines when the gesture is enabled.gesture(_:name:isEnabled:)
: Defines when the gesture is enabled and allows naming the gesture.gesture(_:including:)
: Controls how adding a gesture to the view affects the other gestures that might be associated with it.all
: Enables all gestures.gesture
: Enables the added gesture and disables all other gestures in the subviews.subviews
: Enables all subview gestures but disables the added gesture.none
: Disable all gestures in the subviews and the added gesture.
To create a tap gesture, use the TapGesture
type.
To associate an action with the newly created tap gesture, use the onEnded(_:)
modifier. It defines an action to be triggered when the tap ends, meaning when the user raises the finger.
struct ContentView: View {
@State private var isToggled: Bool = false
var tapGesture = TapGesture()
.onEnded { _ in
isToggled.toggle()
}
var body: some View {
VStack {
Circle()
.fill(isToggled ? Color.blue : Color.orange)
.frame(width: 250, height: 250)
.gesture(tapGesture)
}
}
}
Getting the location of the tap
When you need to know the position of the tap on a view, use the SpatialTapGesture
object. It recognizes one or more taps and reports their location.
struct ContentView: View {
private var tapGesture = SpatialTapGesture()
.onEnded { value in
print(value.location)
}
VStack {
Circle()
.frame(width: 250, height: 250)
.gesture(tapGesture)
}
}
The action closure provides a value of type SpatialTapGesture.Value
, which holds a CGPoint
value representing the x
and y
coordinates of the tap or a Point3D
value for the location of the tap in a 3D context.
Another option to get the tap’s location is to use the onTapGesture(count:coordinateSpace:perform:)
modifier. This modifier allows the definition of the coordinate space from which to receive location values and returns the location of the tap.
struct ContentView: View {
var body: some View {
VStack {
Circle()
.fill(Color.orange)
.frame(width: 250, height: 250)
.onTapGesture(coordinateSpace: .local) { value in
print(value)
}
}
}
}
The coordinate space can be local
, which returns the tap’s location in relation to the view associated with it, or global
, which uses the entire device screen as a reference.