滚动按钮单击 ScrollView/WKWebView、Swift

Scroll on button click a ScrollView/WKWebView, Swift

我正在研究 SwiftUI,但由于没有 WKWebView,我通过 UIViewRepresentable 创建了它。

这是一些代码:

func makeUIView(context: Context) -> WKWebView {

    let jsScript = "var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width'); document.getElementsByTagName('head')[0].appendChild(meta);"

    let userScript = WKUserScript(source: jsScript, injectionTime: .atDocumentEnd, forMainFrameOnly: true)

    let wkController = WKUserContentController()

    wkController.addUserScript(userScript)

    let wkWebConfiguration = WKWebViewConfiguration()

    wkWebConfiguration.userContentController = wkController

    let webView = WKWebView(frame: .null, configuration: wkWebConfiguration)

    webView.translatesAutoresizingMaskIntoConstraints = false

    webView.loadHTMLString(htmlBody, baseURL: nil)
    
    return webView
}

func updateUIView(_ uiView: WKWebView, context: Context) {
    
    if let htmlBody = self.htmlBody {
        uiView.loadHTMLString(htmlBody, baseURL: nil)
    }

}

func makeCoordinator() -> Coordinator {
    Coordinator(self)
}

我需要做的是在单击按钮时滚动到它的底部。

所以在我的 SwiftUI 视图中,我有一个 @State var 并将它传递给我的 UIViewRepresentable。

这是我尝试过的(在我的 updateUIView 中):

  if scrollWebView {
        let scrollPoint = CGPoint(x: 0, y: yourWebView.scrollView.contentSize.height - webView.frame.size.height)
        webView.scrollView.setContentOffset(scrollPoint, animated: true)
  }

但是此代码(单击按钮时)滚动到我的 WkWebView 的顶部。即使我改变了 y 的符号。它总是滚动到顶部而不是底部。

我不认为我可以在我的 SwiftUI 视图中实现这一点,而且我找不到滚动到我的 WKWebView 底部的方法。

我也认为该行为(因为我可以做到 webView.scrollView)与 ScrollView 非常相似。

有什么帮助吗?

这是可能方法的简化演示。测试 Xcode 12 / iOS 14.

struct DemoWebView : UIViewRepresentable {
    let text: String
    @Binding var scrollToBottom: Bool

    func makeUIView(context: Context) -> WKWebView  {
        let webview = WKWebView()
        webview.loadHTMLString(text, baseURL:  nil)
        return webview
    }

    func updateUIView(_ webview: WKWebView, context: Context) {
        if scrollToBottom {
            let point = CGPoint(x: 0, y: webview.scrollView.contentSize.height - webview.frame.size.height)
            webview.scrollView.setContentOffset(point, animated: true)
            DispatchQueue.main.async {
                self.scrollToBottom = false   // turn it back for reuse
            }
        }
    }
}

和用法类似

@State private var scroll = false

var body: some View {
    VStack {
        Button("Bottom") { self.scroll = true }
        DemoWebView(text: self.htmlText, scrollToBottom: $scroll)
    }
}