How can I use combined gestures in SwiftUI?

ByungwookAn
3 min readFeb 2, 2024

--

Intro

In my previous article, I talked about the basic Gesture. In this article, I’ll talk about how I can use combined gestures in SwiftUI and sample code of these combined gestures. If you want to read my previous article, check this link.

I’ll talk about 4 ways to combine gestures, simultaneousGesture, SequenceGesture, ExclusiveGesture, and HighPriorityGesture.

Simultaneous gesture

Simultaneous gesture is a gesture containing two gestures that can happen at the same time with neither of them preceding the other.

It allows you to combine multiple gestures so that they can be recognized simultaneously. This method is the most commonly used of combined gestures.

Here’s sample code of simultaneous gestures.

import SwiftUI

struct GestureExampleView: View {
@State private var scale: CGFloat = 1.0
@State private var rotation: Angle = .degrees(0)

var body: some View {
Image(systemName: "magnifyingglass.circle")
.resizable()
.frame(width: 100, height: 100)
.scaleEffect(scale)
.rotationEffect(rotation)
.gesture(
MagnificationGesture()
.onChanged { value in
self.scale = value
}
.simultaneously(with: RotationGesture()
.onChanged { value in
self.rotation = value
}
)
)

}
}

In this sample code, You can rotate and magnify the circle simultaneously. When you using google maps, You can simultaneously magnify and rotate the map. Also, In many photo editing app, You can simultaneously magnify and rotate the image. Simultaneous gesture is useful gesture in these situations.

Sequence gesture

Sequence gesture is a gesture that’s a sequence of two gestures.

It takes an array of gestures and requires them to be performed in the specified order.

Here’s sample code of sequence gestures.

import SwiftUI

struct GestureExampleView: View {
@State private var message = "Long press then drag"

var body: some View {
let longPress = LongPressGesture()
.onEnded { _ in
message = "Now drag me"
}

let drag = DragGesture()
.onEnded { _ in
message = "Success!"
}

let combined = longPress.sequenced(before: drag)

Text(message)
.gesture(combined)
}
}

When you touched text, the text changed to “Now drag me”. After that, If you drag the text, It cbanged to “Success!”

I brought this sample code in this site because I think their code describes the sequence gesture easy to understand.

https://www.hackingwithswift.com/quick-start/swiftui/how-to-create-gesture-chains-using-sequencedbefore

HighPriorityGesture

High priority gesture allows you to prioritize a gesture over others, making sure it gets recognized first.

It is useful when you want a particular gesture to have higher priority than others.

Here’s sample code of high priority gestures.

import SwiftUI

struct GestureExampleView: View {

var body: some View {
VStack {
Circle()
.fill(Color.blue)
.frame(width: 200, height: 200)
.onLongPressGesture{
print("long press gesture")
}
}
.highPriorityGesture(
TapGesture()
.onEnded { _ in
print("Tap gesture")
}
)
}
}

In this sample code, When you tap the circle, “Tap gesture” printed. But when you press the circle for a second, still “Tap gesture” printed. That’s because Tap gesture has a high priority. Like this situation, If you want to prioritizing between gestures, use highPriorityGesture.

Exclusive gesture

Exclusive gesture is a gesture that consists of two gestures where only one of them can succeed.

This modifier allows a gesture to take exclusive control and prevent other gestures from being recognized concurrently.

Exclusive gesture is the opposite of the Simultaneous gesture.

Here’s sample code of exclusive gesture.

import SwiftUI

struct GestureExampleView: View {
@State private var scale: CGFloat = 1.0
@State private var rotation: Angle = .degrees(0)
@State private var currentPosition: CGSize = .zero

var body: some View {
Image(systemName: "magnifyingglass.circle")
.resizable()
.frame(width: 100, height: 100)
.scaleEffect(scale)
.rotationEffect(rotation)
.offset(currentPosition)
.gesture(
DragGesture()
.onChanged { value in
self.currentPosition = value.translation
}
.onEnded { _ in
self.currentPosition = .zero
}
.exclusively(before:
MagnificationGesture()
.onChanged { value in
self.scale = value
}
.simultaneously(with:
RotationGesture()
.onChanged { value in
self.rotation = value
}
)
)
)
}
}

This code is really similar code with first sample code. But in this code, When you drag the icon, MagnificationGesture() & RotationGesture() are not working. Also, When you magnify & ratate the icon, DragGesture() are not working Simultaneously.

Conclusion

Using appropriate gestures can help improve the User experience. However, improper use of combined gesture can cause confusion for users. So If you want to use combined gesture in your app, you have to lot of testing and consideration.

Reference

https://www.hackingwithswift.com/books/ios-swiftui/how-to-use-gestures-in-swiftui

--

--