Gestures in SwiftUI

Chase
4 min readNov 27, 2023

--

There are so many ways to interact with our phones. If you have ever wanted to see the most popular ways in one place, check out this article.

The word Gestures with 4 emojis of pointing fingers, one on each side of the word, each pointing toward the center of the word

Before we get started, please take a couple seconds to follow me and 👏 clap for the article so that we can help more people learn about this useful content.

Apple Says

The following points are the high level best practice tips from Apple on Gestures: “Always be sure to give people multiple ways to interact with your app”, “In general, respond to gestures in ways that are consistent with other apps on the device”, “Define custom gestures only when necessary”, “Handle gestures as responsively as possible”, “Offer shortcut gestures to supplement standard gestures, not to replace them”, “In iOS, iPadOS, and watchOS, avoid interfering with system-defined screen-edge gestures

For more guidance from Apple, check out the Human Interface Guidelines here: https://developer.apple.com/design/human-interface-guidelines/gestures/

Gestures in SwiftUI

A single (or multiple) tap is one of the most commonly used gestures in SwiftUI. The onTapGesture modifier below allows any view to recognize a tap. One important thing to call out about this new tool is that it shouldn’t be used for every use case where you want to detect a tap on a view. In fact, most of the time you should use a button to detect a tap. That is because a button lets users (especially with accessibility settings like voice over, or even through simple design) know quickly and effortlessly that the element can be interacted with.

You will also see a few State variables below. They are used for the gestures that are more interactive (like drag, magnify, and rotate).

Several of the built in gesture recognizers have parameters that allow us to extend the functionality without much extra code. For example, we can check for a double tap on a view by passing in a “count” of 2 to our onTapGesture parameter.

Another example would be to pass a minimum duration to our longPressGesture. For example, we can pass a minimumDuration of 5 seconds to perform an action after the user has pressed on the view for 5 seconds.

//  ContentView.swift
import SwiftUI

struct ContentView: View {
@State var dragAmount: CGSize = .zero
@State var currentMagnificationAmount = 0.0
@State var finalMagnificationAmount = 1.0
@State var currentRotationAngle: Angle = .zero
@State var finalRotationAngle: Angle = .zero

var body: some View {
List {
Text("Tap Gesture")
.onTapGesture {
print("Tap Gesture Detected")
}

Text("Double Tap")
.onTapGesture(count: 2) {
print("Double Tap Detected")
}

Text("Triple Tap")
.onTapGesture(count: 3) {
print("Triple Tap Detected")
}

Text("Long Press")
.onLongPressGesture {
print("Long Press Detected")
}

Text("Long Press (5 second wait)")
.onLongPressGesture(minimumDuration: 5) {
print("5 second Long Press Detected")
}

Text("Drag Gesture")
.offset(dragAmount)
.gesture(
DragGesture()
.onChanged { drag in
dragAmount = drag.translation
}
.onEnded { _ in
withAnimation {
dragAmount = .zero
}
}
)

Text("Magnification Gesture")
.scaleEffect(currentMagnificationAmount + finalMagnificationAmount)
.gesture(
// Note: This is not a MagnifyGesture()
MagnificationGesture()
.onChanged { amount in
currentMagnificationAmount = amount - 1
}
.onEnded { amount in
finalMagnificationAmount += currentMagnificationAmount
currentMagnificationAmount = 0
}
)

Text("Rotation Gesture")
.rotationEffect(currentRotationAngle + finalRotationAngle)
.gesture(
// Note: this is not a RotateGesture()
RotationGesture()
.onChanged { angle in
currentRotationAngle = angle
}
.onEnded { angle in
finalRotationAngle += currentRotationAngle
currentMagnificationAmount = .zero
}
)
}
}
}

#Preview {
ContentView()
}

If you want to see how to do the same thing in Jetpack Compose, check out another article I wrote here:

If you want to see a side by side comparison for several of the same components built with SwiftUI and Jetpack Compose, check out another article I wrote here:

If you got value from this article, please consider following me, 👏 clapping for this article, or sharing it to help others more easily find it.

If you have any questions on the topic, or know of another way to accomplish the same task, feel free to respond to the post or share it with a friend and get their opinion on it.

If you want to learn more about native mobile development, you can check out the other articles I have written here: https://medium.com/@jpmtech

If you want to see apps that have been built with native mobile development, you can check out my apps here: https://jpmtech.io/apps

Thank you for taking the time to check out my work!

--

--