3
3
.
.
3
3
.
.
1
1
A
A
n
n
i
i
m
m
a
a
t
t
i
i
o
o
n
n
s
s
I
I
n
n
f
f
o
o
[
[
R
R
]
]
[
[
R
R
]
]
[
[
R
R
]
]
[
[
R
R
]
]
View can get animated when some of its Properties change trough @State Variable like: Color, Position, Size, Rotation.
Change in @State Variable redraws the View and by default new Property values are instantly applied to the View.
This means that View will instantly change color, size or move to a new position.
But if animation is applied to the View this change will be gradual - you will see the View moving into the new position.
Animation takes initial and new Property Values (Key frames) and creates animation through interpolation.
Animation can be defined by using
.animation Modifier (implicit animation)
Same Animation is applied every time the View is redrawn (when any State Variable changes)
wrap changes to @State Variable inside a call to withAnimation() (explicit animation)
Different Animation can be applied for the same View (based on Animation specified for each call)
To trigger Animation we need to change some State Variable either inside
Button action which is executed when Button is clicked
.onAppear Modifier which is executed after adding View to Screen (drawn for the first time)
.onTapGesture Modifier which is executed when you tap on the View
Difference between Animation and Transition is that
Animation is performed when View Properties change and View gets redrawn
Transition is performed when View is added or removed from the Hierarchy
.animation Modifier
Text("World")
.offset(x: offset)
.animation(Animation.easeOut(duration: 5))
.onAppear { self.offset = 100 }
withAnimation()
Text("World")
.offset(x: offset)
.onAppear { withAnimation(Animation.easeInOut(duration: 5)) { self.offset = 100 } }
Content
withAnimation()
.onAppear .onAppear { … }
Without Animation self.offset = 100
With Default Animation withAnimation() { self.offset = 100 }
With Custom Animation withAnimation(.easeInOut(duration: 5)) { self.offset = 100 }
Button action action: { … }
Without Animation self.offset = 100
With Default Animation withAnimation() { self.offset = 100 }
With Custom Animation withAnimation(.easeInOut(duration: 5)) { self.offset = 100 }
.animation
.onAppear
Button action
.
.
o
o
n
n
A
A
p
p
p
p
e
e
a
a
r
r
(
(
W
W
i
i
t
t
h
h
o
o
u
u
t
t
A
A
n
n
i
i
m
m
a
a
t
t
i
i
o
o
n
n
)
)
Initially we show Text View with offset = 0.
Using .onAppear we change the offset to 100 as soon as Text View is drawn.
Since offset is State Variable, changing its value redraws the View and Text View is shown at updated position.
This happens so fast that we don't even see the initial position - just the updated with the offset.
Without Animation
struct ContentView : View {
//STATE VARIABLE
@State private var offset:CGFloat = 0
//BODY.
var body: some View {
Text("World")
.offset(x: offset)
.onAppear {
self.offset = 100
}
}
}
Output
.
.
o
o
n
n
A
A
p
p
p
p
e
e
a
a
r
r
(
(
W
W
i
i
t
t
h
h
D
D
e
e
f
f
a
a
u
u
l
l
t
t
A
A
n
n
i
i
m
m
a
a
t
t
i
i
o
o
n
n
)
)
We will now update .onAppear Modifier by enclosing changes to offset Variable inside withAnimation() call.
This tells SwiftUI that if any State variable gets changed inside the body then View should be redrawn using Animation.
Type of Animation is defined inside the call to withAnimation().
In our example we do not provide any parameters so default Animation is used.
This Animation will move the text linearly from the start position into the end position at default speed.
Without Animation
struct ContentView : View {
//STATE VARIABLE
@State private var offset:CGFloat = 0
//BODY.
var body: some View {
Text("World")
.offset(x: offset)
.onAppear {
withAnimation() { self.offset = 100 }
}
}
}
Initial position Final position
.
.
o
o
n
n
A
A
p
p
p
p
e
e
a
a
r
r
(
(
W
W
i
i
t
t
h
h
C
C
u
u
s
s
t
t
o
o
m
m
A
A
n
n
i
i
m
m
a
a
t
t
i
i
o
o
n
n
)
)
Here we give additional parameters to a call to withAnimation() to specify
.easeInOut as the type of Animation we want to use
5 seconds as duration of Animation
Initial and Final positions remain the same but duration of animation is slowed down.
Type of Animation also remains the same since .easeInOut is the default Animation type.
struct ContentView : View {
//STATE VARIABLE
@State private var offset:CGFloat = 0
//BODY.
var body: some View {
Text("World")
.offset(x: offset)
.onAppear {
withAnimation(.easeInOut(duration: 5)) { self.offset = 100 }
}
}
}
B
B
u
u
t
t
t
t
o
o
n
n
a
a
c
c
t
t
i
i
o
o
n
n
(
(
W
W
i
i
t
t
h
h
o
o
u
u
t
t
A
A
n
n
i
i
m
m
a
a
t
t
i
i
o
o
n
n
)
)
Initially we show Text View with offset = 0.
Using Button action we change the offset to 100 when we click on the Button.
Since offset is State Variable, changing its value redraws the View and Text View is shown at updated position.
Since no Animation is applied Text changes position instantaneously after pressing the Button.
Without Animation
struct ContentView : View {
//STATE VARIABLE
@State private var offset:CGFloat = 0
//BODY.
var body: some View {
Button(action: {
self.offset = 100;
}){
Text("Button").offset(x: offset)
}
}
}
Initial position Final position (after pressing the Button)
B
B
u
u
t
t
t
t
o
o
n
n
a
a
c
c
t
t
i
i
o
o
n
n
(
(
W
W
i
i
t
t
h
h
D
D
e
e
f
f
a
a
u
u
l
l
t
t
A
A
n
n
i
i
m
m
a
a
t
t
i
i
o
o
n
n
)
)
We will now update Button action by enclosing changes to offset Variable inside withAnimation() call.
This tells SwiftUI that if any State variable gets changed inside the body then View should be redrawn using Animation.
Type of Animation is defined inside the call to withAnimation().
In our example we do not provide any parameters so default Animation is used.
This Animation will move the text linearly from the start position into the end position at default speed.
With default Animation
struct ContentView : View {
//STATE VARIABLE
@State private var offset:CGFloat = 0
//BODY.
var body: some View {
Button(action: {
withAnimation() { self.offset = 100 }
}){
Text("Button").offset(x: offset)
}
}
}
Initial position Final position (after pressing the Button)
B
B
u
u
t
t
t
t
o
o
n
n
a
a
c
c
t
t
i
i
o
o
n
n
(
(
W
W
i
i
t
t
h
h
C
C
u
u
s
s
t
t
o
o
m
m
A
A
n
n
i
i
m
m
a
a
t
t
i
i
o
o
n
n
)
)
Here we give additional parameters to a call to withAnimation() to specify
.easeInOut as the type of Animation we want to use
5 seconds as duration of Animation
Initial and Final positions remain the same but duration of animation is slowed down.
Type of Animation also remains the same since .easeInOut is the default Animation type.
With default Animation
struct ContentView : View {
//STATE VARIABLE
@State private var offset:CGFloat = 0
//BODY.
var body: some View {
Button(action: {
withAnimation() { self.offset = 100 }
}){
Text("Button").offset(x: offset)
}
}
}
.
.
a
a
n
n
i
i
m
m
a
a
t
t
i
i
o
o
n
n
u
u
s
s
i
i
n
n
g
g
.
.
o
o
n
n
A
A
p
p
p
p
e
e
a
a
r
r
We start with the Code .onAppear (Without Animation).
Then now add .animation Modifier to say that this animation needs to be applied every time Text View is redrawn.
Now after the text View is drawn its .onAppear Modifier is called which changes State Variable offset.
Change in State Variable causes SwiftUI to redraw the View with the new values.
And since Text View has .animation Modifier defined it will be used during redrawing of the View.
This means that Text View will not just suddenly appear at the new position.
Instead there will be an Animation that moves the Text View from the current into the new position.
With Custom Animation
struct ContentView : View {
//STATE VARIABLE
@State private var offset : CGFloat = 0
//BODY.
var body: some View {
Text("World")
.offset(x: offset)
.animation(Animation.easeOut(duration: 5))
.onAppear { self.offset = 100 }
}
}
Initial position Final position (after View is redrawn)
.
.
a
a
n
n
i
i
m
m
a
a
t
t
i
i
o
o
n
n
u
u
s
s
i
i
n
n
g
g
B
B
u
u
t
t
t
t
o
o
n
n
a
a
c
c
t
t
i
i
o
o
n
n
We start with the Code Button action (Without Animation).
Then we add .animation Modifier to say that this animation needs to be applied every time Text View is redrawn.
Now when we press the Button we will see Text Move moving from it initial to the new position.
With Custom Animation
struct ContentView : View {
//STATE VARIABLE
@State private var offset:CGFloat = 0
//BODY.
var body: some View {
Button(action: { self.offset = 100 } ){
Text("Button").offset(x: offset)
.animation(Animation.easeOut(duration: 5))
}
}
}
Initial position Final position (after pressing the Button)