Make a Custom Segmented Progress Bar in SwiftUI
Written by Team Kodeco
Do you want to visually represent different stages of a task in your SwiftUI app? A segmented progress bar is a perfect way to showcase this. Let’s see how you can create one using the SwiftUI framework.
The crucial SwiftUI components you will use are GeometryReader
and HStack
. The GeometryReader
allows you to access the size and coordinate space of its parent view, which is essential for calculating how much of the progress bar should be filled. HStack
is a horizontal stack in which you will put our progress bar segments.
Here’s how you can create a segmented progress bar:
struct ContentView: View {
@State private var progressOne: CGFloat = 0
@State private var progressTwo: CGFloat = 0
@State private var progressThree: CGFloat = 0
var body: some View {
VStack {
GeometryReader { geometry in
HStack(spacing: 0) {
RoundedRectangle(cornerRadius: 10)
.foregroundColor(Color.green)
.frame(height: 10)
.frame(width: progressOne * geometry.size.width / 3)
RoundedRectangle(cornerRadius: 10)
.foregroundColor(Color.blue)
.frame(height: 10)
.frame(width: progressTwo * geometry.size.width / 3)
RoundedRectangle(cornerRadius: 10)
.foregroundColor(Color.purple)
.frame(height: 10)
.frame(width: progressThree * geometry.size.width / 3)
}
.frame(height: 50)
}
Button("Start Task") {
withAnimation(.easeInOut(duration: 2)) {
progressOne = 1.0
}
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
withAnimation(.easeInOut(duration: 2)) {
progressTwo = 1.0
}
}
DispatchQueue.main.asyncAfter(deadline: .now() + 4) {
withAnimation(.easeInOut(duration: 2)) {
progressThree = 1.0
}
}
}
.padding()
Spacer()
}
.padding()
}
}
Your preview should look like this after you tap Start Task:
In this code, you craft a ContentView
that features a single progress bar segmented into three parts. Each segment is embodied by a RoundedRectangle
view. The segments are laid out horizontally within an HStack
, forming a unified progress bar.
Every segment is set to a consistent height of 10 units and is softened with a corner radius of 10 units. The width of each segment is dependent on its corresponding progress variable, progressOne
, progressTwo
or progressThree
. The width of each segment is determined as a proportion of the total width provided by geometry.size.width
, divided by the total number of segments, 3 in this case, to ensure each segment fills its part of the bar as progress ensues.
To visually represent progress within each segment of your custom progress bar, you simply need to update the corresponding progress variables. In this example, this is performed by pressing the Start Task button, which incrementally fills up each segment with a smooth animation, giving you a segmented progress bar that fills over time.
Congratulations! You’ve successfully created a custom segmented progress bar in SwiftUI. Now you can tweak it as per your requirements and enrich your app’s user experience.