Gestures and Animations in SwiftUI

Handle interactions, action, and animations in just a few lines of code

Amol Rai
6 min readDec 19, 2019

Attaching gestures works quite a bit differently in SwiftUI than in UIKit to handle gestures in SwiftUI we have gesture protocol we can also use GestureState property wrapper that works only with gestures.

In this piece, we will look at the DragGesture, LongPressGesture, TapGesture, and RotationGesture.

We will implement all these gestures in our SwiftUI sample application and also we will look at how these gestures work.

If you are preparing for your technical coding interview or you want to learn recursion to improve your problem-solving skills then you should definitely check this free udemy course Master the Recursion from Beginner to Advance Level

If you want to learn ARKit 3 from beginner to expert level then click here to get the course and also you will get 97% discount.

If you are passionate about learning mobile development for iOS and looking to take your iOS development skills to the next level, Core Data with CloudKit framework should be at the top of your list. Click here to get the course and also you will get 97% discount.

Learn SwiftUI from Scratch click here to get the course because in this course we are going to build many apps using SwiftUI such as Facebook clone, News app, Notes app and much more.

Getting Started

Open up Xcode, and create a new Xcode project. Choose Single View App in the iOS template section and click Next.

Enter your product name, and select SwiftUI as the user interface. Click Next, and create it on your desktop.

Here’s what you see once you are done with the setup.

By default, SwiftUI view files declare two structures. The first structure conforms to the View protocol and describes the view’s content and layout. The second structure declares a preview for that view.

Before implementing a bar chart in SwiftUI, let’s first take a look at what a property wrapper is.

What is a state property wrapper?

SwiftUI uses the @State property wrapper to allow us to modify values inside a struct, which would normally not be allowed because structs are value types. When we put @State before a property, we effectively move its storage out from our struct and into shared storage managed by SwiftUI.

This means SwiftUI can destroy and recreate our struct whenever needed (and this can happen a lot) without losing the state it was storing.

Implementation

We start by creating a TapGesture. TapGesture gets called when the user taps the View.

First press Command+N to create a new SwiftUI View file. Call the file TapGestureView, and paste the following code in the TapGestureView.

struct TapGestureView: View {@State private var changeColor = Color.purplevar body: some View {let tapGesture = TapGesture().onEnded { _ inif self.changeColor == Color.purple {
self.changeColor = Color.blue
} else if self.changeColor == .blue {
self.changeColor = Color.red
} else if self.changeColor == .red {
self.changeColor = .orange
} else {
self.changeColor = .purple
}
}
return Circle()
.foregroundColor(changeColor)
.shadow(radius: 10)
.gesture(tapGesture)
.frame(width: 200, height: 200, alignment: .center)
.animation(.default)
}
}

In the above code first, we have one @State variable changeColor to change the color of Circle() after each tap.

Then we have created a Circle() and set the foregroundColor to our @State variable changeColor and finally, we added the gesture and some default animations.

Build and Run

The result looks like this

So after TapGesture our next gesture is LongPressGesture. LongPressGesture gets a call when we long press on the View.

First press Command+N to create a new SwiftUI View file. Call the file LongPressGestureView, and paste the following code in the LongPressGestureView.

struct LongPressGestureView: View {@State private var didLongPress: Bool = false
@State private var scale: CGFloat = 1
@State private var color = Color.red
var body: some View {Circle().scaleEffect(scale)
.frame(width: 210, height: 210, alignment: .center)
.animation(.default)
.foregroundColor(color)
.shadow(radius: 10)
.gesture(LongPressGesture().onEnded({ _ inif self.didLongPress == false {
self.scale = 100
self.color = .blue
} else if self.didLongPress == true {
self.scale = 1
self.color = .red
}
self.didLongPress.toggle()
}))
}
}

In the above code first, we have three @State variable didLongPress , scale and color. We then created Circle() and in the scaleEffect we pass our @State variable scale to scale the Circle()

We then set the frame, and in the foregroundColor we pass our color @State variable to change the color after each LongPress then we set some default animation.

Build and Run

The result looks like this

Now we will implement DragGesture. DragGesture gets called when we drag something such as circle, rectangle, image, etc.

Now press Command+N to create a new SwiftUI View file. Call the file DragGestureView, and paste the following code in the DragGestureView.

struct DragGestureView: View { @State private var drag: CGSize = .zero
@State private var color = Color.blue
var body: some View {Circle()
.frame(width: 120, height: 120, alignment: .center)
.foregroundColor(color)
.shadow(radius: 10)
.animation(.default)
.offset(drag)
.gesture(DragGesture() .onChanged { value in self.drag = value.translation
self.color = .red
} .onEnded({ _ in self.drag = .zero
self.color = .orange
}))
}
}

In the above code first, we have two @State variable drag andcolor. We then created Circle() and in the foregroundColor we pass our @State variable color to the color, after we start dragging the Circle().

we then pass our @State variable drag in the offfset to drag the Circle() and added some default animation and finally we set our DragGesture.

Build and Run

The result looks like this

Last gesture is RoatationGesture. RoatationGesture gets called when we rotate something such as circle, rectangle, image, etc.

Now press Command+N to create a new SwiftUI View file. Call the file RoatationGestureView, and paste the following code in the RoatationGestureView.

struct RotationGestureView: View {@State var rotation: Angle = .zero
@State var color = Color.red
var body: some View {let rotationGesture = RotationGesture().onChanged { value in self.rotation = value
self.color = .orange
}return Rectangle() .foregroundColor(color)
.cornerRadius(40)
.shadow(radius: 10)
.animation(.default)
.rotationEffect(rotation)
.frame(width: 200, height: 200, alignment: .center)
.gesture(rotationGesture)
}
}

In the above code first, we have two @State variable rotation andcolor we then created our RoatationGesture and set our Rectangle() and set it’s foregroundColor to our @State variable color to change the Rectangle() color after we start rotating our Rectangle() and in the rotationEffect we pass our @State variable rotation and finally, we added our RoatationGesture with some default animations.

Build and Run

The result looks like this

Conclusion

That’s it for this piece. I hope you enjoyed this piece, and you have learned how to interact with gestures in SwiftUI.

If you are preparing for your technical coding interview or you want to learn recursion to improve your problem-solving skills then you should definitely check this free udemy course Master the Recursion from Beginner to Advance Level

Additional Resources

If you want to learn ARKit 3 from beginner to expert level then click here to get the course and also you will get 97% discount.

If you are passionate about learning mobile development for iOS and looking to take your iOS development skills to the next level, Core Data with CloudKit framework should be at the top of your list. Click here to get the course and also you will get 97% discount.

Learn SwiftUI from Scratch click here to get the course because in this course we are going to build many apps using SwiftUI such as Facebook clone, News app, Notes app and much more.

--

--

Amol Rai

Software Engineer @TIFINfintech | Prev SDE Intern @UserologyHQ | Building Frontend Lab