Circular Progress Bar
Beschreibung
Die CircularProgressBar ist eine wiederverwendbare SwiftUI-Komponente, mit der du einen animierten, kreisförmigen Fortschrittsbalken inklusive Prozentanzeige erstellen kannst.
Sie eignet sich für Lade-, Download- oder Status-Visualisierungen in iOS-, iPadOS- und macOS-Apps.
🔍 Zweck
- Visuelle Darstellung von Fortschrittswerten (0 – 100 %) als Kreisdiagramm
- Anpassbar über
lineWidth
, Farb-Gradienten und Bindings - Enthält eine Demo-View mit Slider und Zufalls-Button, um das Verhalten direkt auszuprobieren
📄 Codebeispiel
import SwiftUI
struct CircularProgressBar: View {
/// The progress value (between 0.0 and 1.0)
@Binding var progress: Double
var lineWidth: CGFloat = 20
var gradientColors: [Color] = [Color.blue, Color.green]
var body: some View {
ZStack {
// Background circle
Circle()
.stroke(
Color.gray.opacity(0.2),
style: StrokeStyle(lineWidth: lineWidth)
)
.shadow(color: Color.black.opacity(0.05), radius: 5, x: 0, y: 2)
// Foreground circle with gradient
Circle()
.trim(from: 0.0, to: min(progress, 1.0))
.stroke(
AngularGradient(
gradient: Gradient(colors: gradientColors),
center: .center
),
style: StrokeStyle(lineWidth: lineWidth, lineCap: .round)
)
.rotationEffect(.degrees(-90))
.shadow(color: gradientColors.last!.opacity(0.3), radius: 10, x: 0, y: 5)
.animation(.easeOut(duration: 0.8), value: progress)
// Percentage label
Text("\(Int(progress * 100))%")
.font(.system(size: 40, weight: .bold, design: .rounded))
.foregroundStyle(
.linearGradient(
colors: gradientColors,
startPoint: .topLeading,
endPoint: .bottomTrailing
)
)
.shadow(color: Color.black.opacity(0.15), radius: 2, x: 1, y: 2)
}
.frame(width: 180, height: 180)
}
}
// Interactive demo
struct CircularProgressBarDemo: View {
@State private var progress: Double = 0.5
var body: some View {
VStack(spacing: 32) {
CircularProgressBar(progress: $progress)
Slider(value: $progress, in: 0...1)
.padding(.horizontal, 40)
Button("Random Progress") {
withAnimation {
progress = Double.random(in: 0...1)
}
}
.buttonStyle(.borderedProminent)
}
.padding()
}
}
#Preview {
CircularProgressBarDemo()
}