Индикатор активности в SwiftUI - PullRequest
13 голосов
/ 07 июня 2019

Попытка добавить полноэкранный индикатор активности в SwiftUI.

Я могу использовать функцию .overlay(overlay: ) в протоколе View.

С этим я могу наложить любое представление, но не могу найти стиль по умолчанию для iOS UIActivityIndicatorView эквивалентный в SwiftUI.

Как сделать спиннер стиля по умолчанию сSwiftUI?

ПРИМЕЧАНИЕ: Речь идет не о добавлении индикатора активности в инфраструктуру UIKit.

1 Ответ

36 голосов
/ 07 июня 2019

Многие представления еще не представлены в 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"].identified(by: \.self)) { row in
                    Text(row)
                }.navigationBarTitle(Text("A List"), displayMode: .large)
            }
        }
    }

}

Результат:

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...