TechnologiesSwiftUI

CircularProgressViewStyle struct

iOSmacOStvOSwatchOSvisionOSiOS 14.0+✓ renders

A progress view that uses a circular gauge to indicate the partial

How it works

CircularProgressViewStyle is a concrete ProgressViewStyle that renders a ProgressView as a circular, spinner-like indicator rather than a horizontal bar. You reach for it when you want to apply the system's circular treatment explicitly — for an indeterminate activity spinner or a determinate ring driven by a fractional value. Because it conforms to ProgressViewStyle, you pass an instance to the progressViewStyle(_:) modifier, and SwiftUI uses it to lay out and draw every progress view in that subtree.

  1. Construct the style and hand it to progressViewStyle(_:)

    A style has no effect on its own; it takes hold when you pass an instance to the progressViewStyle(_:) modifier on a ProgressView. Calling CircularProgressViewStyle() builds the default circular look, as in .progressViewStyle(CircularProgressViewStyle()), and SwiftUI applies it to the attached progress view and any progress views nested inside it.

  2. Tint the indicator with the tint: initializer

    The tint: initializer parameter colors the moving portion of the circle — the spinning arc or the filled ring. Supplying a Color such as in CircularProgressViewStyle(tint: .pink) overrides the inherited accent color for that progress view, so the indicator reads in your chosen hue instead of the default.

  3. Drive determinate vs. indeterminate from the ProgressView

    CircularProgressViewStyle adapts to how its ProgressView is configured. A view built with only a label, like ProgressView("Loading"), has no known fraction, so the style draws a continuously spinning indeterminate circle; a view built with ProgressView(value: 0.4) reports completion, so the same style draws a partially filled determinate ring.

  4. Rely on the ProgressViewStyle conformance for reuse

    Because CircularProgressViewStyle conforms to ProgressViewStyle, a single application cascades to descendants. Placing the modifier on each ProgressView here keeps them independent, but moving a .progressViewStyle(...) up onto an enclosing container would style every progress view beneath it without repeating the call.

Try it — Change ProgressView(value: 0.4) to ProgressView(value: 0.9) to watch the determinate ring fill nearly all the way around while the circular style stays the same.

Example & preview

Press Run live & edit to compile it in your browser — then edit the Swift on the left and the preview re-renders live.

CircularProgressViewStyle.swift
struct CircularProgressViewStyleDemo: View {
    var body: some View {
        VStack(spacing: 16) {
            ProgressView("Loading")
                .progressViewStyle(CircularProgressViewStyle())
            ProgressView(value: 0.4)
                .progressViewStyle(CircularProgressViewStyle(tint: .pink))
        }
        .padding()
    }
}
Live preview
Loading
Loading
swift → lexer → parser → sema → uiir → canvas Open in Studio ↗
What's new in SwiftUI 27 →