带有自动布局的 UIScrollView 中的 UIWebView

UIWebView in UIScrollView with autolayout

我在使用此设置时遇到了很多问题。所以基本上我显示了一些高度可变的标签,然后是一个按钮,在视图的末尾我需要一个 WebView 来显示一些 HTML 格式的文本。

我按如下方式加载内容时调整 Web 视图高度限制。

func webViewDidFinishLoad(webView: UIWebView) {
        nContentViewHeight.constant = webView.scrollView.contentSize.height
}

首次加载视图时,效果很好。滚动很好,所有网页视图内容都可见。

但是当我旋转设备时,我不知道如何正确调整网络视图的大小。我尝试在

中再次加载内容
override func didRotateFromInterfaceOrientation(fromInterfaceOrientation: UIInterfaceOrientation)

这样 webViewDidFinishLoad 将再次触发并调整网络视图的大小。但这根本不起作用,因为 web 视图中滚动视图的 contentSize 没有改变。

不知道为什么我尝试了非常丑陋的解决方案,那就是:

func fitWebAndScrollView(){
    let newRect = CGRectMake(nContentWebView.frame.minX, nContentWebView.frame.minY, self.view.frame.width, 10)
    let newWebView = UIWebView(frame: newRect)
    newWebView.delegate = self
    newWebView.tag = -12
    newWebView.scrollView.scrollEnabled = false
    self.view.addSubview(newWebView)
    newWebView.loadHTMLString(contentHtml, baseURL: nil)
}

override func didRotateFromInterfaceOrientation(fromInterfaceOrientation: UIInterfaceOrientation) {
    fitWebAndScrollView()
}

func webViewDidFinishLoad(webView: UIWebView) {
    nContentViewHeight.constant = webView.scrollView.contentSize.height
    if webView.tag == -12 {
        webView.removeFromSuperview()
        nContentViewHeight.constant *= 1.1 // longer the content is more of it is clipped
    }
}

这种方法有效,但在某些情况下,WebView 内容的底部被剪裁,就好像内部滚动视图内容大小计算不正确一样。

有人处理过这个问题吗?我一直认为这种事情不是一个额外的特殊用例。

谢谢你的想法。

首先,如果代码真的如上所示,你是在把内容的width赋值给height常量。这肯定会导致问题。 (显然它不是如图所示;请显示实际代码,而不是在问题中输入新的 "similar" 代码……)

其次,仅在webViewDidFinishLoad中检测内容高度并不是一种非常可靠的方法。在某些网站上,实际调用之前可能需要很长时间,但内容可能仍然可用,当然用户在浏览器中的任何操作都可能更改它,许多网站在页面末尾附加更多内容苍蝇(例如,当用户向下滚动时)。

此外,我希望您意识到 scrollView.contentSize 是内容本身的大小(不是可见部分),并且它的高度不会随旋转而改变,除非以某种方式改变宽度内容布局更改。

总的来说,我认为您可能正在尝试做一些 UIWebView 根本不适合的事情。您应该只自动布局 webview 本身的大小,而不是将其放在外部 UIScrollView 中(如果我正确阅读了标题并且这就是您正在做的)。它的内部 scrollView 将自动为您处理内容滚动,而不是与您的外部 scrollView 冲突。如果您需要对来自内部滚动视图的事件做出反应等,您可以将自己设置为内部滚动视图的委托。

要在旋转时调整 UIWebView 自身的大小,请设置约束以将其每条边与周围视图的距离绑定(或使用更简单的 autoresizingMask)。在 didRotateFromInterfaceOrientation 中应该不需要做任何事情(如果您确实需要手动布局,请在 viewWillLayoutSubviews and/or viewDidLayoutSubviews 中进行)。

好吧,我就是这样解决的

func fitWebAndScrollView(){
    if let strH = nContentWebView.stringByEvaluatingJavaScriptFromString("document.getElementById(\"cnt\").offsetHeight;"),
    numH = NSNumberFormatter().numberFromString(strH){
        nContentViewHeight.constant = CGFloat(numH)+20
    }
}

override func didRotateFromInterfaceOrientation(fromInterfaceOrientation: UIInterfaceOrientation) {
    fitWebAndScrollView()
}

func webViewDidFinishLoad(webView: UIWebView) {
    fitWebAndScrollView()
}

问题实际上出在我用作包装器的 HTML 代码上。

let htmlWrapperString = "<html><head>\n<style type=\"text/css\">body {font-family: \"%@\"; font-size: %@;-webkit-text-size-adjust: none;}</style></head><body><div id=\"cnt\">%@</div></body></html>"

所以在我没有在正文中包装 div 之前,当我查询正文标签的高度时,它总是返回整个视口大小,而不仅仅是正文中的文本高度。

现在它可以可靠地工作了。