Gestures
Overview
Subjects
Using Gestures
Tags: #MagnificationGesture #onChanged #RotationGesture #rotationEffect
Magnification
struct ContentView: View {
@State private var currentAmount = 0.0
@State private var finalAmount = 1.0
var body: some View {
Text("Hello, World!")
.scaleEffect(finalAmount + currentAmount)
.gesture(
MagnificationGesture()
.onChanged { amount in
currentAmount = amount - 1
}
.onEnded { amount in
finalAmount += currentAmount
currentAmount = 0
}
)
}
}
Rotation
struct ContentView: View {
@State private var currentAmount = Angle.zero
@State private var finalAmount = Angle.zero
var body: some View {
Text("Hello, World!")
.rotationEffect(currentAmount + finalAmount)
.gesture(
RotationGesture()
.onChanged { angle in
currentAmount = angle
}
.onEnded { angle in
finalAmount += currentAmount
currentAmount = .zero
}
)
}
}
Tapping
struct ContentView: View {
var body: some View {
VStack {
Text("Hello, World!")
.onTapGesture {
print("Text tapped")
}
}
.onTapGesture {
print("VStack tapped")
}
}
}
Dragging
Tags: #offset #DragGesture #CGSize #RotationEffect #removal #swipe
Tags: #Swipe #Drag #DifferentiateWithoutColor #xmark #checkmark
For colorblinds you may should use graphics instead of colors. Differentiate Without Color will help on this purpose.
High Priority Gesture
As default, SwiftUI gives priority to child gesture. To overcome that we should define the parent Gesture as a highpriority.
struct ContentView: View {
var body: some View {
VStack {
Text("Hello, World!")
.onTapGesture {
print("Text tapped")
}
}
.highPriorityGesture(
TapGesture()
.onEnded { _ in
print("VStack tapped")
}
)
}
}
Simultaneous Gesture
Trigers all the gestures at the same time.
struct ContentView: View {
var body: some View {
VStack {
Text("Hello, World!")
.onTapGesture {
print("Text tapped")
}
}
.simultaneousGesture(
TapGesture()
.onEnded { _ in
print("VStack tapped")
}
)
}
}
Sequential Gestures
First needs to be long pressed, an than it activates the second gesture.
struct ContentView: View {
// how far the circle has been dragged
@State private var offset = CGSize.zero
// whether it is currently being dragged or not
@State private var isDragging = false
var body: some View {
// a drag gesture that updates offset and isDragging as it moves around
let dragGesture = DragGesture()
.onChanged { value in offset = value.translation }
.onEnded { _ in
withAnimation {
offset = .zero
isDragging = false
}
}
// a long press gesture that enables isDragging
let pressGesture = LongPressGesture()
.onEnded { value in
withAnimation {
isDragging = true
}
}
// a combined gesture that forces the user to long press then drag
let combined = pressGesture.sequenced(before: dragGesture)
// a 64x64 circle that scales up when it's dragged, sets its offset to whatever we had back from the drag gesture, and uses our combined gesture
Circle()
.fill(.red)
.frame(width: 64, height: 64)
.scaleEffect(isDragging ? 1.5 : 1)
.offset(offset)
.gesture(combined)
}
}
Solutions / Examples
Dynamic Emoji
https://twitter.com/philipcdavis/status/1580211607627390976?s=12&t=PW_LE1rEl7C8W6gcTx0V3g
Sources
Videos
Articles / Documents
See also
Last updated
Was this helpful?