Trying to add a full screen activity indicator in SwiftUI.
.overlay(overlay: )
プロトコルで関数を使用できますView
。
UIActivityIndicatorView
これを使えば、任意のビューオーバーレイを作成できますが、iOS のデフォルトスタイルに相当するものが見つかりませんSwiftUI
。
でデフォルト スタイルのスピナーを作成するにはどうすればよいですかSwiftUI
?
注意:これは、UIKit フレームワークにアクティビティ インジケーターを追加することではありません。
ベストアンサー1
Xcode 12 ベータ版( iOS 14 )以降、開発者は と呼ばれる新しいビューProgressView
を利用でき、確定的な進行状況と不確定な進行状況の両方を表示できます。
スタイルはデフォルトで に設定されておりCircularProgressViewStyle
、まさにこれが私たちが求めているものです。
var body: some View {
VStack {
ProgressView()
// and if you want to be explicit / future-proof...
// .progressViewStyle(CircularProgressViewStyle())
}
}
11.x の場合
かなりの数のビューがまだ に表現されていませんSwiftUI
が、それらをシステムに移植するのは簡単です。 をラップしてUIActivityIndicator
にする必要がありますUIViewRepresentable
。
(これについての詳細は、WWDC 2019 の優れた講演「SwiftUI の統合」でご覧いただけます)
struct ActivityIndicator: UIViewRepresentable {
@Binding var isAnimating: Bool
let style: UIActivityIndicatorView.Style
func makeUIView(context: UIViewRepresentableContext<ActivityIndicator>) -> UIActivityIndicatorView {
return UIActivityIndicatorView(style: style)
}
func updateUIView(_ uiView: UIActivityIndicatorView, context: UIViewRepresentableContext<ActivityIndicator>) {
isAnimating ? uiView.startAnimating() : uiView.stopAnimating()
}
}
次に、次のように使用します。これは読み込みオーバーレイの例です。
注:実装で何が起こっているかを正確に把握できるように、ZStack
ではなくを使用することを好みます。overlay(:_)
struct LoadingView<Content>: View where Content: View {
@Binding var isShowing: Bool
var content: () -> Content
var body: some View {
GeometryReader { geometry in
ZStack(alignment: .center) {
self.content()
.disabled(self.isShowing)
.blur(radius: self.isShowing ? 3 : 0)
VStack {
Text("Loading...")
ActivityIndicator(isAnimating: .constant(true), style: .large)
}
.frame(width: geometry.size.width / 2,
height: geometry.size.height / 5)
.background(Color.secondary.colorInvert())
.foregroundColor(Color.primary)
.cornerRadius(20)
.opacity(self.isShowing ? 1 : 0)
}
}
}
}
これをテストするには、次のサンプルコードを使用できます。
struct ContentView: View {
var body: some View {
LoadingView(isShowing: .constant(true)) {
NavigationView {
List(["1", "2", "3", "4", "5"], id: \.self) { row in
Text(row)
}.navigationBarTitle(Text("A List"), displayMode: .large)
}
}
}
}
結果: