kokobob.com

Mastering Gestures in SwiftUI: A Comprehensive Guide

Written on

Introduction to SwiftUI Gestures

SwiftUI streamlines the implementation of gestures, enabling developers to enhance productivity. The framework includes several built-in gestures commonly utilized in Apple devices, such as tap, long press, drag, and magnification. In this guide, we will explore how to implement these gestures in SwiftUI.

This guide is part of my ongoing series.

Getting Started with Tap Gestures

Before delving into more complex gestures, let's start with a basic example. We will create a tappable view that triggers a function upon being tapped. Below is the code snippet:

import SwiftUI

struct ContentView: View {

var body: some View {

VStack {

Text("Tap me!")

.foregroundColor(.white)

.padding()

}

.background(.blue)

.onTapGesture {

print("It works")

}

}

} // ContentView

Run the application and tap the created stack view. Xcode should output the following message each time the view is tapped:

It works

You can also customize the onTapGesture to respond to multiple taps by adding a count parameter. Modify the .onTapGesture as follows:

.onTapGesture(count: 2) {

print("It works")

}

Now, the stack will only respond to double taps.

Long Press Gestures

Next, let's explore the long press gesture. By using the .onLongPressGesture modifier, we can create an interactive heart image that scales upon being long pressed. Here’s how:

import SwiftUI

struct ContentView: View {

@State private var isTapped = false

var body: some View {

Image(systemName: "heart.fill")

.font(.system(size: 150))

.foregroundColor(.red)

.scaleEffect(isTapped ? 0.5 : 1.0)

.animation(.linear, value: isTapped)

.onLongPressGesture(minimumDuration: 1.0) {

self.isTapped.toggle()

}

}

} // ContentView

The minimumDuration parameter specifies how long the object must be pressed (in seconds) for the effect to take place. We added animation to avoid a dull experience during the long press.

Run the application and try long pressing the heart image; it should scale down when pressed.

Utilizing the Gesture Modifier

For more advanced functionality, the .gesture modifier allows you to implement multiple built-in gestures. Here’s a simple example of using long press within the .gesture modifier:

struct ContentView: View {

@State private var isTapped = false

var body: some View {

Image(systemName: "heart.fill")

.font(.system(size: 150))

.foregroundColor(.red)

.scaleEffect(isTapped ? 0.5 : 1.0)

.animation(.linear, value: isTapped)

.gesture(

LongPressGesture(minimumDuration: 1.0)

.onEnded({ _ in

self.isTapped.toggle()

})

)

}

} // ContentView

This code snippet yields the same result as the previous example. We also introduced the onEnded() modifier to capture and execute the final value of the gesture.

Using GestureState for Better Management

The GestureState property wrapper allows automatic resetting of the property once the gesture concludes. Although the standard state property wrapper can achieve this, it requires additional coding. For instance, if we want a sun image to change color when tapped and scale up when long pressed, here’s the code:

import SwiftUI

struct ContentView: View {

@State private var isTapped = false

@GestureState private var isLongPressTapped = false

var body: some View {

Image(systemName: "sun.max.fill")

.font(.system(size: 150))

.foregroundColor(isLongPressTapped ? .orange : .yellow)

.scaleEffect(isTapped ? 2.0 : 1.0)

.animation(.easeInOut, value: isTapped)

.gesture(

LongPressGesture(minimumDuration: 1.0)

.updating($isLongPressTapped, body: { value, state, transaction in

state = value

})

.onEnded({ _ in

self.isTapped.toggle()

})

)

}

} // ContentView

The updating() modifier is responsible for modifying the state, with three parameters: value, state, and transaction.

Run the application; a single tap on the sun image will change its color, and a long press will scale it up.

Implementing Drag Gestures

With a solid understanding of the gesture modifier and GestureState, we can now learn how to implement drag gestures. Modify your existing code to include the following:

import SwiftUI

struct ContentView: View {

@GestureState private var dragOffset = CGSize.zero

var body: some View {

Image(systemName: "sun.max.fill")

.font(.system(size: 150))

.foregroundColor(.yellow)

.offset(x: dragOffset.width, y: dragOffset.height)

.gesture(

DragGesture()

.updating($dragOffset, body: { value, state, transaction in

state = value.translation

})

)

}

} // ContentView

This allows the image to be dragged anywhere on the screen. The state is updated to reflect the current position of the image during the drag.

To make the image stay where it is dropped, modify the code as follows:

import SwiftUI

struct ContentView: View {

@GestureState private var dragOffset = CGSize.zero

@State private var position = CGSize.zero

var body: some View {

Image(systemName: "sun.max.fill")

.font(.system(size: 150))

.foregroundColor(.yellow)

.offset(x: position.width + dragOffset.width, y: position.height + dragOffset.height)

.gesture(

DragGesture()

.updating($dragOffset, body: { value, state, transaction in

state = value.translation

})

.onEnded({ value in

self.position.height += value.translation.height

self.position.width += value.translation.width

})

)

}

} // ContentView

Now, the sun image can be dragged and will remain in the position where you drop it.

Magnification Gesture

Lastly, we’ll implement a magnification gesture, often used in image applications. Start by ensuring you have a sample image available. Here’s the code for implementing the magnification gesture:

import SwiftUI

struct ContentView: View {

@GestureState private var imageScale = 1.0

var body: some View {

Image("austin-poon")

.resizable()

.scaledToFill()

.scaleEffect(imageScale)

.gesture(

MagnificationGesture()

.updating($imageScale, body: { value, state, transaction in

state = value.magnitude

})

)

}

} // ContentView

This code captures the default scale of the image as a variable wrappe

Share the page:

Twitter Facebook Reddit LinkIn

-----------------------

Recent Post:

How to Transform Your Daily Commute into a Self-Improvement Hour

Discover how to turn your daily commute into a productive self-improvement session.

# Embrace the Positives: AI as the Key to Transformation

Explore how Appreciative Inquiry can transform organizations by focusing on strengths rather than weaknesses.

Reflections on Aging and Identity in Hemingway's Work

Exploring themes of aging, dignity, and identity through the lens of Hemingway's