import SwiftUI struct ACProgressView: View { @State var isDeterminate: Bool = false @State var progress: CGFloat = 0 @State var text: String? = nil @State var isAnimating: Bool = false var body: some View { ZStack(alignment: .center) { Color.black.opacity(0.4) VStack { VStack(spacing: 24) { if self.isDeterminate { ZStack { Circle() .stroke(Color.secondary.opacity(0.2), style: StrokeStyle(lineWidth: 4)) .frame(width: 100, height: 100) Circle() .trim(from: 0, to: self.progress) .stroke(Color.blue, style: StrokeStyle(lineWidth: 4)) .rotationEffect(.degrees(-90)) .frame(width: 100, height: 100) Text("\(Int(self.progress*100)) %") } } else { let gradient = AngularGradient( gradient: Gradient(colors: [Color.blue, Color.blue.opacity(0.01)]), center: .center, startAngle: .degrees(360), endAngle: .degrees(0)) Circle() .stroke(gradient, style: StrokeStyle(lineWidth: 4)) .rotationEffect(Angle(degrees: self.isAnimating ? 360 : 0)) .onAppear { withAnimation(.linear(duration: 1).repeatForever(autoreverses: false)) { self.isAnimating = true } } .onDisappear(perform: { self.isAnimating = false }) .frame(width: 100, height: 100) } if let msg = self.text { Text(msg) } } .padding(28) } //.frame(width: 160, height: 160) .background(.regularMaterial) .cornerRadius(20) } .edgesIgnoringSafeArea(.all) } } struct ACProgressView_Previews: PreviewProvider { static var previews: some View { Group { ACProgressView() ACProgressView(isDeterminate: true, progress: 0.3, text: "Loading...") .preferredColorScheme(.dark) } } }