Reputation: 41
I am having lots of trouble with this setup. So basically I am displaying some labels with variable height then a button and at the end of the view i need a WebView to display some HTML formatted text.
I resize the web view height constraint when the content is loaded as follows.
func webViewDidFinishLoad(webView: UIWebView) {
nContentViewHeight.constant = webView.scrollView.contentSize.height
}
When the view is first loaded, this works perfectly. The scrolling is good and all the web view content is visible.
But when I rotate the device I don't know how to properly resize the web view. I tried loading the content again in
override func didRotateFromInterfaceOrientation(fromInterfaceOrientation: UIInterfaceOrientation)
so that webViewDidFinishLoad
would trigger again and resize the web view. But that doesn't work at all because the contentSize of the scrollview inside the web view doesn't change.
Not knowing why I attempted very ugly solution and that is this:
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
}
}
And this sort of works, but in some instance the bottom of the WebView content is clipped as if the inner scrollview content size is calculated incorrectly.
Has anybody dealt with this before? I always assumed that this sort of thing wasn't an extra special use case.
Thank you for your ideas.
Upvotes: 2
Views: 1451
Reputation: 41
Aright so I managed to solve it this way
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()
}
The problem was actually with the HTML code I was using as a wrapper.
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>"
So before I didn't have that wrapping div in the body and when I queried the height of body tag it always returned the whole view port size and not just the text height that was in body.
Now it works reliably.
Upvotes: 2
Reputation: 42149
First of all, if the code is really as shown, you are assigning the width of the content to the height constant. This would definitely cause the issue. (Apparently it is not as shown; please show actual code instead of typing in new "similar" code into the question…)
Second, it is not a very reliable way to detect the content height by only doing it in webViewDidFinishLoad
. On some sites it may take a long time before this is actually called but the content may still be usable, and of course any action by the user in the browser may change it, and many websites append more content to the end of the page on the fly (e.g., as the user scrolls down).
Also, I hope you realize that scrollView.contentSize
is the size of the content itself (not the visible part), and its height won't change on rotation unless the width is changed in a way that makes the content layout change.
Overall I think you may be trying to do something that UIWebView
is simply not suited for. You should only autolayout the size of the webview itself, not have it inside an external UIScrollView
(if I read the title correctly and that's what you are doing). Its inner scrollView
will then handle the content scrolling for you automatically, instead of conflicting with your external scrollView. You can set yourself up as the delegate of the inner scrollview if you need to react to events from it, etc.
To resize the UIWebView
itself on rotation, set up constraints to bind the distance from each of its edges to the surrounding views (or use the simpler autoresizingMask
). There should be no need to do anything in didRotateFromInterfaceOrientation
(and if you do need manual layout, do it in viewWillLayoutSubviews
and/or viewDidLayoutSubviews
).
Upvotes: 1