SwiftUI Animations: A Guide to Creating Delightful User Interfaces
Animations are an essential part of creating modern and engaging user interfaces. They help convey the flow and behavior of an app, making it feel more responsive and dynamic. SwiftUI, Apple’s modern declarative UI framework, provides a simple and powerful way to create animations that are both expressive and easy to customize.
In this article, we’ll explore the basics of creating animations with SwiftUI and demonstrate how they can be used to add life and personality to your apps.
Getting Started with SwiftUI Animations
Before we dive into the details of SwiftUI animations, let’s start with a basic example. We’ll create a simple animation that fades in and out a text view when a button is pressed.
struct ContentView: View {
@State private var isShowingText = false
var body: some View {
VStack {
Button("Show Text") {
withAnimation {
isShowingText.toggle()
}
}
if isShowingText {
Text("Hello, World!")
.transition(.opacity)
}
}
}
}In this example, we’re using the @State property wrapper to keep track of whether the text view should be shown or hidden. When the button is pressed, we toggle the value of isShowingText inside a withAnimation closure. This tells SwiftUI to animate the transition between the two states.
The transition(.opacity) modifier specifies that the animation should use a fade in/out effect to show and hide the text view.
Animating View Properties
In addition to transitioning between different views, SwiftUI animations can also be used to animate changes to view properties. Let’s modify our example to animate the font size of the text view when it’s shown.
struct ContentView: View {
@State private var isShowingText = false
var body: some View {
VStack {
Button("Show Text") {
withAnimation {
isShowingText.toggle()
}
}
if isShowingText {
Text("Hello, World!")
.font(.title)
.transition(.opacity)
.animation(.spring())
}
}
}
}We’ve added the .font(.title) modifier to the text view to increase its font size. We've also chained a .animation(.spring()) modifier to specify that the animation should use a spring effect instead of the default linear animation.
Animating View Layout
In addition to animating view properties, SwiftUI also provides ways to animate changes to view layout. For example, we can animate the position and size of a view using the offset and scaleEffect modifiers.
struct ContentView: View {
@State private var isShowingText = false
var body: some View {
VStack {
Button("Show Text") {
withAnimation {
isShowingText.toggle()
}
}
if isShowingText {
Text("Hello, World!")
.font(.title)
.transition(.opacity)
.offset(y: -50)
.scaleEffect(1.2)
}
}
}
}In this example, we’ve added the .offset(y: -50) modifier to move the text view up by 50 points. We've also added the .scaleEffect(1.2) modifier to increase the size of the view by 20%.
Animating Multiple Views
So far, we’ve only animated a single view at a time. But what if we want to animate multiple views together? SwiftUI provides several ways to do this.
One approach is to use a Group view to group multiple views together and apply the animation to the group. Let's modify our example to animate both the text view and the button at the same time.
struct ContentView: View {
@State private var isShowingText = false
var body: some View {
Group {
Button("Show Text") {
withAnimation {
isShowingText.toggle()
}
}
if isShowingText {
Text("Hello, World!")
.font(.title)
.transition(.opacity)
.offset(y: -50)
.scaleEffect(1.2)
}
}
}
}We’ve wrapped both the button and the text view inside a Group view. We've also removed the VStack and the if statement, since the group automatically lays out its children vertically.
Now, when the button is pressed, both the button and the text view are animated together.
Animating Transitions Between Views
So far, we’ve only used the transition modifier to specify how a view should appear and disappear during an animation. But what if we want more control over the transition animation itself?
SwiftUI provides a powerful AnyTransition type that allows you to create custom transition animations between two views. Let's modify our example to use a custom transition that spins the text view as it appears and disappears.
struct SpinTransition: ViewModifier {
let angle: Angle
let opacity: Double
func body(content: Content) -> some View {
content
.rotationEffect(angle)
.opacity(opacity)
}
}
extension AnyTransition {
static var spin: AnyTransition {
.modifier(active: SpinTransition(angle: .degrees(360), opacity: 0),
identity: SpinTransition(angle: .degrees(0), opacity: 1))
}
}
struct ContentView: View {
@State private var isShowingText = false
var body: some View {
Group {
Button("Show Text") {
withAnimation {
isShowingText.toggle()
}
}
if isShowingText {
Text("Hello, World!")
.font(.title)
.modifier(SpinTransition(angle: .degrees(0), opacity: 1))
.transition(.spin)
.offset(y: -50)
.scaleEffect(1.2)
}
}
}
}We’ve created a custom view modifier called SpinTransition that rotates and fades a view. We've also extended the AnyTransition type to create a custom transition called .spin that uses our SpinTransition modifier.
In the ContentView, we've applied the SpinTransition modifier to the text view and used the .spin transition to animate the transition between the hidden and visible states.
Conclusion
SwiftUI provides a powerful and flexible way to create animations that bring your user interfaces to life. Whether you’re animating view properties, layout, or transitions between views, SwiftUI’s declarative syntax and built-in animation effects make it easy to create delightful and engaging user experiences.
In this article, we’ve covered the basics of creating animations with SwiftUI, including animating view properties, layout, and transitions between views. We’ve also shown how to create custom transition animations using the AnyTransition type.
By mastering SwiftUI animations, you can create apps that feel responsive, dynamic, and delightful to use.
Thanks
I write about Software development, coffee and general topics. Much grateful to you for following me and my stories. Happy to have you here, and would like to make it worth your time.





