SwiftUI 如何在 WKWebView 中添加事件指示器?

标签 swiftui wkwebview uiactivityindicatorview

如何在 WKWebView 中添加事件指示器,它会在网页加载时显示指示器并在加载时消失?

我看过一些旧帖子,但不知道如何在 SwiftUI 中做到这一点
请参阅以下旧解决方案之一的链接
How to add Activity Indicator to WKWebView (Swift 3)

最佳答案

使用 UIViewRepresentable创建一个 UIActivityIndicatorView :

You control when an activity indicator animates by calling the startAnimating() and stopAnimating() methods. To automatically hide the activity indicator when animation stops, set the hidesWhenStopped property to true.

You can set the color of the activity indicator by using the color property.

struct ActivityIndicatorView: UIViewRepresentable {
    @Binding var isAnimating: Bool
    let style: UIActivityIndicatorView.Style
    
    func makeUIView(context: UIViewRepresentableContext<ActivityIndicatorView>) -> UIActivityIndicatorView {
        return UIActivityIndicatorView(style: style)
    }
    
    func updateUIView(_ uiView: UIActivityIndicatorView, context: UIViewRepresentableContext<ActivityIndicatorView>) {
        isAnimating ? uiView.startAnimating() : uiView.stopAnimating()
    }
}
创建一个 LoadingView允许您环绕您的 View :
这允许您设置事件 View 内容的样式。
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...")
                    ActivityIndicatorView(isAnimating: .constant(true), style: .large)
                }
                .frame(width: geometry.size.width / 2, height: geometry.size.height / 5)
                .background(Color.secondary.colorInvert())
                .foregroundColor(Color.red)
                .cornerRadius(20)
                .opacity(self.isShowing ? 1 : 0)
                
            }
        }
    }
}
如果您希望能够更新 LoadingView(...) status 你需要引入一个从 ObservableObject 继承的 View 模型:
基于此答案:https://stackoverflow.com/a/58825642/264802
class WebViewModel: ObservableObject {
    @Published var url: String
    @Published var isLoading: Bool = true
    
    init (url: String) {
        self.url = url
    }
}

struct WebView: UIViewRepresentable {
    @ObservedObject var viewModel: WebViewModel
    let webView = WKWebView()

    func makeCoordinator() -> Coordinator {
        Coordinator(self.viewModel)
    }
    
    class Coordinator: NSObject, WKNavigationDelegate {
        private var viewModel: WebViewModel
        
        init(_ viewModel: WebViewModel) {
            self.viewModel = viewModel
        }

        func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
            self.viewModel.isLoading = false
        }
    }
    
    func updateUIView(_ uiView: UIView, context: UIViewRepresentableContext<WebView>) { }
    
    func makeUIView(context: Context) -> UIView {
        self.webView.navigationDelegate = context.coordinator

        if let url = URL(string: self.viewModel.url) {
            self.webView.load(URLRequest(url: url))
        }

        return self.webView
    }
}
然后在您的 View 中使用它,您将执行以下操作:
struct ContentView: View {
    @ObservedObject var model = WebViewModel(url: "http://www.google.com")

    var body: some View {
        LoadingView(isShowing: self.$model.isLoading) {
            WebView(viewModel: self.model)
        }
    }
}

关于SwiftUI 如何在 WKWebView 中添加事件指示器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60051231/

相关文章:

ios - SwiftUI:如何在背景模糊的当前 View 之上将 View 显示为弹出窗口?

ios - WKWebView 在后台应用程序时停止音频

ios - UIActivityIndi​​catorView 不显示/开始动画

ios事件指示器与后台交互

swiftui - 当按钮文本也有图像时如何居中?

swiftui - 我可以使用 SwiftUI .currency 格式样式增加小数位数吗?

swiftui - NavigationBarTitle 导致 TabView 内出现错误

ios - 如何知道 WKContentRuleList 阻止了什么

ios - WKWebView 不加载某些 URL

swift - 滚动后在 Collection View 单元格上随机显示事件指示器