肘子的 Swift 记事本

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)
             )
        }
    }
}

I'm really looking forward to hearing your thoughts! Please Leave Your Comments Below to share your views and insights.

Fatbobman(东坡肘子)

I'm passionate about life and sharing knowledge. My blog focuses on Swift, SwiftUI, Core Data, and Swift Data. Follow my social media for the latest updates.

You can support me in the following ways