Amos Gyamfi
Amos GyamfiSeptember 5, 2022

Creating a Progress bar Animation in SwiftUI

Learn how to create an animating loading progress bar view in SwiftUI using shape, width, frame and animation modifiers.
Creating a Progress bar Animation in SwiftUI

This is the fourth tutorial in our series on the basics of animation in SwiftUI. If you missed the last article, you can find it here. This article will focus on animating a simple progress bar – or loading indicator – and styling it.

This is what the end result will look like:

Creating a Progress bar Animation in SwiftUI

Creating the Loading animation

To start, create a blank SwiftUI project or a view file in Xcode and name it ProgressAnimation.swift.

  1. Define the state variable @State private var drawingWidth = false. This will be used to change the frame properties and determine our progress over time.
  2. Draw your bars. Lay the background and foreground views inside a ZStack and color them accordingly. The background view will be the gray background and the foreground view will have an indigo gradient.
ZStack(alignment: .leading) {
    RoundedRectangle(cornerRadius: 3)
        .fill(Color(.systemGray6))
    RoundedRectangle(cornerRadius: 3)
        .fill(.indigo.gradient)
}
  1. Set the frame of the ZStack with .frame(width: 250, height: 12). This will set the width of the ZStack to 250 and the height to 12, aligning the rectangles to the leading edge.
  2. Set the frame of the progress rectangle with .frame(width: drawingWidth ? 250 : 0, alignment: .leading). This will set the width to full if the state variable is true and 0 if it is false. You can also tie this to a floating-point variable that represents progress instead of a boolean.
  3. Attach the animation to the bar with .animation(.easeInOut(duration: 10).repeatForever(autoreverses: false), value: drawingWidth).
  4. Animate on appear by toggling the state variable.
.onAppear {
    drawingWidth.toggle()
}
  1. Extra: add a label and set a leading alignment.
VStack(alignment: .leading) {
    Text("RAM")
        .bold()
 
    // Add your bar here
}

Let's put it all together:

import SwiftUI
 
struct ProgressAnimation: View {
    @State private var drawingWidth = false
 
    var body: some View {
        VStack(alignment: .leading) {
            Text("RAM")
                .bold()
 
            ZStack(alignment: .leading) {
                RoundedRectangle(cornerRadius: 3)
                    .fill(Color(.systemGray6))
                RoundedRectangle(cornerRadius: 3)
                    .fill(.indigo.gradient)
                    .frame(width: drawingWidth ? 250 : 0, alignment: .leading)
                    .animation(.easeInOut(duration: 10).repeatForever(autoreverses: false), value: drawingWidth)
            }
            .frame(width: 250, height: 12)
            .onAppear {
                drawingWidth.toggle()
            }
        }
    }
}

And boom, we're done!

Going Further

Now that we've seen the basics, you could start exploring with this animation. What if you attached the progress of the bar to a floating-point variable that represents progress instead of a boolean? Or maybe you could add a visual cue to it, change styling and shapes or even turn it into a reusable view. You decide this time around!