Gauge Style in SwiftUI

In iOS 16, SwiftUI introduces a new view called Gauge for displaying progress. You can actually use it to show values within a range.

Style_01: In the most basic form, a gauge has a default range from 0 to 1. If we set the value parameter to 0.7, SwiftUI renders a progress bar indicating the task is 70% complete

//1
struct ContentView1: View {
    @State private var progress = 0.7
    var body: some View {
        Gauge(value: progress) {
            Text("Upload Status")
        }
    }
}

We can provide optionally minimum, maximum & current values:

struct ContentView2: View {
    
    @State private var progress = 0.7
    
    var body: some View{
        Gauge(value: progress) {
            Text("Upload Status")
        } currentValueLabel: {
            Text(progress.formatted(.percent))
        } minimumValueLabel: {
            Text(0.formatted(.percent))
        } maximumValueLabel: {
            Text(100.formatted(.percent))
        }
        .padding()
    }
}

Step_02: Using Custom Range

The default range is set to 0 and 1. That said, you can provide your custom range. For example, you are building a speedometer with the maximum speed of 200km/h. You can specify the range in the in parameter:

struct SpeedoMeterView: View {
    
    @State private var currentSpeed = 100.0
    
    var body: some View {
        Gauge(value: currentSpeed, in: 0...200) {
            Text("Speed")
        } currentValueLabel: {
            Text("\(currentSpeed.formatted(.number))km/h")
        } minimumValueLabel: {
            Text(0.formatted(.number))
        }maximumValueLabel: {
            Text(200.formatted(.number))

Step_03: Using Image Labels

We change the text label of the gauge to a system image. And, for the current value label, we create a stack to arrange the image and text.

struct CustomImageView: View {
    
    @State private var currentSpeed = 100.0
    
    var body: some View {
        Gauge(value: currentSpeed, in: 0...200) {
            Image(systemName: "gauge.medium")
                .font(.system(size: 50))
        }currentValueLabel: {
            HStack(content: {
                Image(systemName: "gauge.high")
                Text("\(currentSpeed.formatted(.number))km/h")
            })
        }minimumValueLabel: {
            Text(0.formatted(.number))
        }maximumValueLabel: {
            Text(200.formatted(.number))
        }
    }
}

Customazing tint color using .tint(.yellow)

struct CustomImageView: View {
    
    @State private var currentSpeed = 100.0
    
    var body: some View {
        Gauge(value: currentSpeed, in: 0...200) {
            Image(systemName: "gauge.medium")
                .font(.system(size: 50))
        }currentValueLabel: {
            HStack(content: {
                Image(systemName: "gauge.high")
                Text("\(currentSpeed.formatted(.number))km/h")
            })
        }minimumValueLabel: {
            Text(0.formatted(.number))
        }maximumValueLabel: {
            Text(200.formatted(.number))
        }
        .tint(.yellow)
    }
}

Step_05: The look & feel of the Gauge view is very similar to that of ProgressView. Optionally, you can customize the Gauge view using the gaugeStyle modifier. The modifier supports several built-in styles.

  1. linearCapacity

This is the default style that displays a bar that fills from leading to trailing edges.

2. accessoryLinear

This style displays a bar with a point marker to indicate the current value.

struct CustomImageView: View {
    
    @State private var currentSpeed = 100.0
    
    var body: some View {
        Gauge(value: currentSpeed, in: 0...200) {
            Image(systemName: "gauge.medium")
                .font(.system(size: 50))
        }currentValueLabel: {
            HStack(content: {
                Image(systemName: "gauge.high")
                Text("\(currentSpeed.formatted(.number))km/h")
            })
        }minimumValueLabel: {
            Text(0.formatted(.number))
        }maximumValueLabel: {
            Text(200.formatted(.number))
        }
        .tint(.yellow)
        .gaugeStyle(.accessoryLinear)
    }
}

3. accessoryLinearCapacity

For this style, the gauge is still displayed as a progress bar but it’s more compact.

struct CustomImageView: View {
    
    @State private var currentSpeed = 100.0
    
    var body: some View {
        Gauge(value: currentSpeed, in: 0...200) {
            Image(systemName: "gauge.medium")
                .font(.system(size: 50))
        }currentValueLabel: {
            HStack(content: {
                Image(systemName: "gauge.high")
                Text("\(currentSpeed.formatted(.number))km/h")
            })
        }minimumValueLabel: {
            Text(0.formatted(.number))
        }maximumValueLabel: {
            Text(200.formatted(.number))
        }
        .tint(.yellow)
        .gaugeStyle(.accessoryLinearCapacity)
    }
}

4. accessoryCircular

Instead of displaying a bar, this style displays an open ring with a point marker to indicate the current value.

struct CustomImageView: View {
    
    @State private var currentSpeed = 100.0
    
    var body: some View {
        Gauge(value: currentSpeed, in: 0...200) {
            Image(systemName: "gauge.medium")
                .font(.system(size: 50))
        }currentValueLabel: {
            HStack(content: {
                Image(systemName: "gauge.high")
                Text("\(currentSpeed.formatted(.number))km/h")
            })
        }minimumValueLabel: {
            Text(0.formatted(.number))
        }maximumValueLabel: {
            Text(200.formatted(.number))
        }
        .tint(.yellow)
        .gaugeStyle(.accessoryCircular)
    }
}

5. accessoryCircularCapacity

This style displays a closed ring that’s partially filled in to indicate the gauge’s current value. The current value is also displayed at the center of the gauge.

struct CustomImageView: View {
    
    @State private var currentSpeed = 100.0
    
    var body: some View {
        Gauge(value: currentSpeed, in: 0...200) {
            Image(systemName: "gauge.medium")
                .font(.system(size: 50))
        }currentValueLabel: {
            HStack(content: {
                Image(systemName: "gauge.high")
                Text("\(currentSpeed.formatted(.number))km/h")
            })
        }minimumValueLabel: {
            Text(0.formatted(.number))
        }maximumValueLabel: {
            Text(200.formatted(.number))
        }
        .tint(.yellow)
        .gaugeStyle(.accessoryCircularCapacity)
    }
}

6 thoughts on “Gauge Style in SwiftUI

Leave a Reply

Your email address will not be published. Required fields are marked *