带有自动布局的 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 之前,当我查询正文标签的高度时,它总是返回整个视口大小,而不仅仅是正文中的文本高度。
现在它可以可靠地工作了。
我在使用此设置时遇到了很多问题。所以基本上我显示了一些高度可变的标签,然后是一个按钮,在视图的末尾我需要一个 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 之前,当我查询正文标签的高度时,它总是返回整个视口大小,而不仅仅是正文中的文本高度。
现在它可以可靠地工作了。