swift 如何解决WKWebView较小内容高度值问题?

68de4m5k  于 2023-03-17  发布在  Swift
关注(0)|答案(3)|浏览(288)

我正在WebView中加载Html内容。
当我在WebView中加载Html内容时,它显示正确。之后,当我用新的Html内容刷新WebView时,问题出现了。
例如:我的第一个Html内容的高度是900,它显示正确,然后我重新加载WebView与我的新Html内容,有一个高度是400,WebView是不是缩小和适应的内容与新的高度。它仍然保持只要900的高度。
因此,WebView似乎能够将自己从以前加载的较少内容重新调整为更多内容,但当内容少于以前加载的内容时,无法重新调整自己的大小。
网络视图

struct WebView: UIViewRepresentable {
    @State var htmlString: String
    @Binding var dynamicHeight: CGFloat

    func makeUIView(context: Context) -> WKWebView {
        let webView: WKWebView = WKWebView()
        webView.navigationDelegate = context.coordinator
        webView.scrollView.bounces = false
        webView.backgroundColor = .clear
        return webView
    }

    func updateUIView(_ uiView: WKWebView, context: Context) {
        uiView.loadHTMLString(htmlString, baseURL: nil)
    }

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

    class Coordinator: NSObject, WKNavigationDelegate {
        var parent: WebView

        init(_ parent: WebView) {
            self.parent = parent
        }

        func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
            webView.evaluateJavaScript("document.readyState", completionHandler: { (complete, error) in
                if complete != nil {
                   webView.evaluateJavaScript("document.documentElement.scrollHeight", completionHandler: { (result, error) in
                            if let height = result as? CGFloat {
                                self.parent.dynamicHeight = height
                            }
                    })
                }
            })
        }
    }
}

我使用WebView查看的任何内容

struct WebTest: View {

    @ObservedObject var viewModel = NewsVM()
    @State var index: Int = 0
    @State var newID: String = ""
    let screen = UIScreen.main.bounds
    let formatString = "<html><head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=0\"><script type=\"text/javascript\" src=\"https://platform.twitter.com/widgets.js\"></script><style>@media (prefers-color-scheme: dark) { body { background-color: #1c1c1e; color: white; }} img,iframe,blockquote {\n\t\t\tmax-width: \(UIScreen.main.bounds.width - 24);\n\t\t\theight: auto\n\t\t}\n\t\t</style></head><body><span style=\"font-family: '-apple-system', 'HelveticaNeue'; font-size:17\">%@</span></body></html>"
    @State private var webViewHeight: CGFloat = .zero

    init(id:String) {
        viewModel.fetchNews(id: id)
        self.newID = id
    }

    var body: some View {
        Group{
            if self.viewModel.news.count > 0 {
                        ModelPages(self.viewModel.news, currentPage: self.$index, wrap: false, hasControl: false) { pageIndex, new in
                        ScrollView(.vertical, showsIndicators: false){
                            Text("Height: \(self.webViewHeight)").padding()
                            WebView(htmlString: String(format: self.formatString, new.content), dynamicHeight: self.$webViewHeight)
                                    .frame(width: self.screen.width - 16)
                                    .frame(height: self.webViewHeight)
                                    .tag(pageIndex)
                                    .padding(.horizontal, 8)
                            }
                        }
            }else{
                Group{
                    if self.viewModel.error == true{
                        ConnectionError()
                    }else{
                        LoadingView()
                    }
                }
            }
        }
    }
}
ctehm74n

ctehm74n1#

我从这个解决方案开始解决这个问题:https://stackoverflow.com/a/41511422/5965343
1.监视onresize事件,但添加了以下内容。
1.在ondocument ready事件、正文结尾处添加/注入<span id="endElement"></span>
1.获取跨度端元素Y,以获得“真实”高度。
1.将结果高度放在webView.frame.Height上
要使用 AddUserScript() onloadFunction注入的函数

window.onload=function () {window.webkit.messageHandlers.sizeNotification.postMessage({justLoaded:true,height: document.body.scrollHeight,endElement:document.getElementById('endOfDocument').offsetTop});};

调整大小

document.body.onresize=function() {window.webkit.messageHandlers.sizeNotification.postMessage({justLoaded:false,height: document.body.scrollHeight,endElement:document.getElementById('endOfDocument').offsetTop});};

结束时的进样范围

document.body.insertAdjacentHTML('beforeend',"<span style='height: 0;' id='endOfDocument'></span>" );
pod7payv

pod7payv2#

能否尝试将Webview Package 在父UIView中并加载页面。不要对UIView设置固定高度约束,而是让Webview定义父UIView的高度。这可能会起作用。

57hvy0tb

57hvy0tb3#

我在CollectionView中遇到过类似的问题,包括 accordion ,WKWebView中的可扩展Web数据。由于最后一个可扩展Web项目,它无法滚动到底部,并使用以下解决方案解决了这个问题:

class WebViewCollectionViewCell: WKNavigationDelegate {
    @IBOutlet private var webView: WKWebView!
    
    private var cancellable: AnyCancellable?
    var onWebViewFinished: ((CGFloat) -> Void)?
    
    func webView(_: WKWebView, didFinish _: WKNavigation!) {
        webView.contentHeight { [weak self] height in
            self?.onWebViewFinished?(height)
            UIView.animate(withDuration: 0.4) {
                self?.webView.alpha = 1 // Fix white flashing
            }
        }
        cancellable = webView?
            .publisher(for: \.scrollView.contentSize)
            .removeDuplicates()
            .sink { [weak self] size in
                self?.onWebViewFinished?(size.height)
            }
    }
}

extension WKWebView {
    func contentHeight(completion: @escaping ((CGFloat) -> Void)) {
        evaluateJavaScript("document.readyState") { [weak self] complete, _ in
            if complete.exists {
                self?.evaluateJavaScript("document.body.scrollHeight", completionHandler: { height, _ in
                    completion(height as? CGFloat ?? 0)
                })
            }
        }
    }
}

以及UICollectionViewCell闭包的用法:

class ViewController: 
 UIViewController, 
 UICollectionViewDelegate,
 UICollectionViewDataSource,
 UICollectionViewDelegateFlowLayout {

private var webViewHeight: CGFloat = 1_000
private lazy var configurator: CollectionViewCell = {
  cell.onWebViewFinished = { height in
                self?.webViewHeight = height
                self?.onWebViewFinished?()
            }
            return cell
    }

相关问题