How to Pause and Resume Animation in SwiftUI (with chaining)

SwiftUI doesn’t have built-in functionality to pause/resume animations. The same is true for animation chaining. So let’s see how we can solve this

Concept

Stop/Resume animations

To stop the animation, we can use a zero-length animation and the current value of the property being animated

withAnimation(.easeInOut(duration: 0)) {
propertyValue = propertyCurrentValue
}

To resume just run the same animation but the duration must be calculated as totalDuration-(pausedTime-startedTime)

withAnimation(.easeInOut(duration: remainingTime)) {
propertyValue = propertyFinalValue
}

Such logic can be encapsulated in an AnimatableModifier and easily applied to any property we want to stop/resume

.offset(x: xOffset)
.modifier(PauseModifier(
propertyValue: $xOffset,
propertyFinalValue: 100,
duration: 0.5
))

Chaining

Imagine we have a complex animation consisting of many animations with different durations, intervals, start and end times

But they can be anchored to the “parent” animation timeline. In this case, Total Duration is the duration of the complex animation. The Current Time is a kind of player timer. When we pause a player, it stops counting, if we press play it will keep counting

Each animation (AnimatableModifier) should calculate or receive the Current Time value and run if the Current Time == startTime. I think updating the Current Time (scheduling) is a good job for a manager. Summarising, updating the Current Time is necessary at the pause and startTime of each animation

Solution

PauseModifierManager was created to manage complex animations. You can use multiple managers on one screen. The current implementation loops animations, but it’s easy to modify. maxTime can be bigger than Total Duration depending on your needs

@ObservedObject private var animationManager = PauseModifierManager(maxTime: 5)

“Child” animations must be created by the manager

.modifier(animationManager.modifier(
propertyValue: $xOffset,
propertyFinalValue: 100,
startTime: 2.3,
endTime: 3.1
))

The illustration below describes how the PauseModifierManager works internally
Welcome to read the source code!

--

--

iOS developer and Android dev in the past

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store