HowTo —— Using ProgressView in SwiftUI 2.0 to Display Progress Bars

Published on

Get weekly handpicked updates on Swift and SwiftUI!

SwiftUI 2.0 introduced some convenient built-in controls, such as Label and ProgressView. They have a basic form that is quite common but support custom styles. The intention of the official team is quite clear: by using built-in controls, they aim to standardize code and speed up prototype writing. If more detailed control is needed, it can be achieved by extending the style.

Classic Spinning Indicator

Swift
ProgressView()

progress1

Linear Progress Bar

Swift
ProgressView("Completion", value: 50, total: 100)

Screenshot 2020-07-11 at 4.09.34 PM

Code Example

Swift
import SwiftUI

struct ProgressTest: View {
    @State var timer = Timer.TimerPublisher(interval: 0.03, runLoop: .main, mode: .common).autoconnect()
    @State var value: Double = 0.0
    var body: some View {
        List {
            // Unable to define color
            ProgressView()
            
            // Unable to hide Label
            ProgressView("Completion", value: value, total: 100)
                .accentColor(.red)
            // Custom Style
            ProgressView("Project Progress", value: value, total: 100)
                .progressViewStyle(MyProgressViewStyle())
        }
        .onAppear {
            timer = Timer.TimerPublisher(interval: 0.03, runLoop: .main, mode: .common).autoconnect()
        }
        .onReceive(timer) { _ in
            if value < 100 {
                value += 2
            }
        }
    }
}

// The method definitions are more or less the same.
struct MyProgressViewStyle: ProgressViewStyle {
    let foregroundColor: Color
    let backgroundColor: Color
    init(foregroundColor: Color = .blue, backgroundColor: Color = .orange) {
        self.foregroundColor = foregroundColor
        self.backgroundColor = backgroundColor
    }
    func makeBody(configuration: Configuration) -> some View {
        GeometryReader { proxy in
            ZStack(alignment: .topLeading) {
                backgroundColor
                Rectangle()
                    .fill(foregroundColor)
                    .frame(width: proxy.size.width * CGFloat(configuration.fractionCompleted ?? 0.0))
            }.clipShape(RoundedRectangle(cornerRadius: 10))
             .overlay(
                configuration.label
                    .foregroundColor(.white)
             )
        }
    }
}
Weekly Swift & SwiftUI insights, delivered every Monday night. Join developers worldwide.
Easy unsubscribe, zero spam guaranteed