SwiftUI WebView ( WKWebView ) autoHeight [英] SwiftUI WebView ( WKWebView ) autoHeight

查看:77
本文介绍了SwiftUI WebView ( WKWebView ) autoHeight的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用自动高度创建 WebView.

I'm trying to create WebView with autoheight.

我必须以与多行相同的方式显示一些内容 Text() :如果它的内容变大 - 它必须自动放大我的 WebView 的高度

I'ts must to display some content in the same way as multiline Text() : If it's content become bigger - its must automatically enlarge height of my WebView

我的代码是一组蹩脚的黑客,而且效果非常糟糕.

My code is a set of lame hacks and it's works really bad.

import SwiftUI
import WebKit

@available(OSX 11.0, *)
public struct WebView: View {
    @Binding var html: String
    
    public init (html: Binding<String> ){
        _html = html
    }
    
    public var body: some View {
        WebViewWrapper(html: html)
    }
}

@available(OSX 11.0, *)
public struct WebViewWrapper: NSViewRepresentable {
    let html: String
    
    public func makeNSView(context: Context) -> WKWebView {
        return WKWebView()
    }
    
    public func updateNSView(_ webView: WKWebView, context: Context) {
        webView.loadHTMLString(html, baseURL: nil)
        webView.actualateHeight()
        
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) {
            webView.actualateHeight()
        }
    }
    
}

fileprivate extension WKWebView {
    func actualateHeight(){
        self.setFrameHeight(1)
        
        self.evaluateJavaScript("document.readyState", completionHandler: { (complete, error) in
                if complete != nil {
                    self.evaluateJavaScript("document.body.scrollHeight", completionHandler: { (height, error) in
                        
                        if let height = height {
                            self.setFrameHeight(height as! Float)
                        }
                    })
                }
            })
    }
    
    func setFrameHeight(_ height: Float) {
        let size = NSSize(width: self.frame.width, height: CGFloat(height) )
        self.setFrameSize(size)
        self.setBoundsSize(size)
        
        print("YYY \(height)")
    }
}

用法:

struct PreferencesView : View {
    var model : Config

    @ObservedObject var splittedStatusWindow : ConfigProperty<Bool>
    
    @State var text: String = "<html> <style>body{background-color:linen;} H1 {font-size: 50;} .testClass { color: red; } #hell{ color: green;}</style> <body><h1 class='testClass'>Hello World</h1><p id='hell'><strong>hell</strong> yeah!</p></body></html>"
    
    init(model: Config) {
        self.model = model
        self.splittedStatusWindow = model.splitedStatusWindow
        
    }
    
    var body: some View {
        Spacer()

        TextField("", text: $text)
                
        Divider()
        
        WebView(html: $text)
            .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
        
        Divider()

        Spacer()
    }
}

代码问题:

  1. hacky 解决方案无法自动更新大小
  2. 代码周围的包装器大小大于预期.总是.

例如:

但预期某事:

推荐答案

import SwiftUI
import WebKit

@available(OSX 11.0, *)
public struct WebView: View {
    @Binding var html: String
    @State var dynamicHeight: CGFloat = 10
    
    public init ( html: Binding<String> ) {
        _html = html
    }
    
    public var body: some View {
        WebViewWrapper(html: html, dynamicHeight: $dynamicHeight)
            .frame(height: dynamicHeight)
    }
}

@available(OSX 11.0, *)
public struct WebViewWrapper: NSViewRepresentable {
    let html: String
    @Binding var dynamicHeight: CGFloat
    
    public func makeNSView(context: Context) -> NoScrollWKWebView {
        let a = NoScrollWKWebView()
        a.navigationDelegate = context.coordinator
        
        return a
    }
    
    public func updateNSView(_ webView: NoScrollWKWebView, context: Context) {
        webView.loadHTMLString(html, baseURL: nil)
    }
    
    public func makeCoordinator() -> Coordinator { Coordinator(self) }
}

@available(OSX 11.0, *)
public extension WebViewWrapper {
    class Coordinator: NSObject, WKNavigationDelegate {
        var parent: WebViewWrapper
        
        public init(_ parent: WebViewWrapper) {
            self.parent = parent
        }
        
        public func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
            webView.evaluateJavaScript("document.documentElement.scrollHeight", completionHandler: { (height, error) in
                DispatchQueue.main.async {
                    self.parent.dynamicHeight = height as! CGFloat
                }
            })
        }
    }
}


public class NoScrollWKWebView: WKWebView {
    public override func scrollWheel(with theEvent: NSEvent) {
        nextResponder?.scrollWheel(with: theEvent)
    }
}

这篇关于SwiftUI WebView ( WKWebView ) autoHeight的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆