18
Feb
2021
Progress Dialog / HUD in SwiftUI
Reading time: 1 min
This recipe shows how to render a progress dialog / HUD in SwiftUI.
The end result looks like this:
This component is available as a Swift Package in this repo.
In order to make this happen, we'll use the custom view dialog from this recipe. If you haven't yet, be sure to check it out!
OK, here's the code:
extension View {
func progressDialog(isShowing: Binding<Bool>, message: String) -> some View {
self.genericDialog(isShowing: isShowing, cancelOnTapOutside: false) {
HStack(spacing: 10) {
if #available(iOS 14.0, *) {
ProgressView()
.progressViewStyle(CircularProgressViewStyle())
} else {
ActivityIndicator(isAnimating: true)
}
Text(message).bodyText
}.padding()
}
}
}
Then, you can use it like any other dialog:
struct MyView: View {
@State private var isLoading = false
var body: some View {
VStack {
Text("Content")
}.progressDialog(isShowing: $isLoading, message: "Loading...")
}
}
The ActivityIndicator
is an iOS 13-compatible replacement for circular ProgressView
, and here is its code:
struct ActivityIndicator: UIViewRepresentable {
public typealias UIView = UIActivityIndicatorView
public var isAnimating: Bool = true
public var configuration = { (indicator: UIView) in }
public init(isAnimating: Bool, configuration: ((UIView) -> Void)? = nil) {
self.isAnimating = isAnimating
if let configuration = configuration {
self.configuration = configuration
}
}
public func makeUIView(context: UIViewRepresentableContext<Self>) -> UIView {
UIView()
}
public func updateUIView(_ uiView: UIView, context: UIViewRepresentableContext<Self>) {
isAnimating ? uiView.startAnimating() : uiView.stopAnimating()
configuration(uiView)
}
}
extension View where Self == ActivityIndicator {
func configure(_ configuration: @escaping (Self.UIView) -> Void) -> Self {
Self.init(isAnimating: self.isAnimating, configuration: configuration)
}
}