Activity indicator in SwiftUI Ask Question

Activity indicator in SwiftUI Ask Question

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)
            }
        }
    }

}

結果:

ここに画像の説明を入力してください

おすすめ記事