6

I have a view controller containing some labels and a UIWebView that is loading some html in it. All these labels and UIWebView are subviews of a UIScrollView. I have disabled the scrolling of UIWebView so the labels and UIWebView scrolls all together inside the UIScrollView.

Then i took found the size of the content inside the UiWebView, changed the UIWebView size according to the content size and then set the size of the scroll view to the size of the webview. This is how i did it by adding the following code in webViewDidFinishLoad:

CGRect frame = myWebView.frame;
frame.size.height = 1;
myWebView.frame = frame;
CGSize fittingSize = [myWebView sizeThatFits:CGSizeZero];
frame.size = fittingSize;
myWebView.frame = frame;

NSLog(@"size: %f, %f", fittingSize.width, fittingSize.height);

mainScrollView.contentSize = myWebView.bounds.size; 

As i am using NSLog to see the size of the content of webview, i noticed that it gives different height for the same content. For example, if i open the view controller the first time, it shows the height equal to 915.0 and when i move back in the navigation and come back to this view controller, then the log will show the size to be 1012.0.

I believe it might be due to the images loading in the html content. Can anybody tell how can i fix it to show the right height the first time? Thanks!

UPDATE: If i use a different strategy using javascript, that i have already tried using the following code:

CGRect oldBounds = [[self myWebView] bounds];
CGFloat height = [[myWebView stringByEvaluatingJavaScriptFromString:@"document.height"] floatValue];
NSLog(@"NEW HEIGHT %f", height);
[myWebView setBounds:CGRectMake(oldBounds.origin.x, oldBounds.origin.y, oldBounds.size.width, height)];
mainScrollView.contentSize = myWebView.bounds.size;

This code gives me the right height every time in the log which is exactly i want but the whole webview is shifted a little upward blocking all the labels above it. Am i doing something wrong and how to fix it? Thanks!

AJ112
  • 5,291
  • 7
  • 45
  • 60
  • Are you logging the scroll view too? That may show an interesting result. Any xib warning messages? – ICL1901 Oct 22 '13 at 12:37
  • and this question may help: http://stackoverflow.com/questions/6440448/ios-uiwebview-inside-a-uiscrollview?rq=1 or this: http://stackoverflow.com/questions/8089992/content-change-when-uiwebview-load-inside-scrollview?rq=1 – ICL1901 Oct 22 '13 at 12:38
  • @DavidDelMonte if i use NSString *webHeight = [myWebView stringByEvaluatingJavaScriptFromString:@"document.height;"]; NSLog(@"WebView Height %@", webHeight); then it shows the exact height everytime but here webHeight is a NSString, how do i set the height of myWebView to the height of webHeight ?? – AJ112 Oct 22 '13 at 12:54
  • what if you use NSInteger *webHeightInt = [webHeight intValue]; (top of my head, don't try this at home.. (or NSUInteger) – ICL1901 Oct 22 '13 at 13:23
  • I am also struggling with keeping content steady within a UIScrollView. It seems a little dodgy. Especially when you add device rotation into the mix. – ICL1901 Oct 22 '13 at 13:24
  • @DavidDelMonte well in my case i dont have to deal with device rotation. I am dealing just with the Portrait mode. I think using the document.height javascript is the right choice. All i need to find is how to set the webview height to this nsstring and the problem will be resolved – AJ112 Oct 22 '13 at 13:34
  • Try using this to get the content height. [webview stringByEvaluatingJavaScriptFromString:@"document.body.scrollHeight"] – Ramaraj T Oct 25 '13 at 06:05
  • @Suresh a different javascript worked for me but still remains one issue, see my update. Thanks! – AJ112 Oct 25 '13 at 21:36

3 Answers3

10

This is a very common problem when you try to embed a UIWebView And Other views inside a UIScrollView.

SOLUTION 1: You have already explained the first solution in your question. How ever this solution is only valid when there is only text involved in the UIWebView inside the UIScrollView. If there are images and ajax or any such thing that lazily loads, this solution won't give you the right height the first time.

CGRect frame = myWebView.frame;
frame.size.height = 1;
myWebView.frame = frame;
CGSize fittingSize = [myWebView sizeThatFits:CGSizeZero];
frame.size = fittingSize;
myWebView.frame = frame;

NSLog(@"size: %f, %f", fittingSize.width, fittingSize.height);

mainScrollView.contentSize = myWebView.bounds.size; 

SOLUTION 2: The other solution is using javascript. It gives you the right height everytime but you will face weird issues that i am unable to troubleshoot. In your case, you said that the whole view is shifted a little updwards.

CGRect oldBounds = [[self myWebView] bounds];
CGFloat height = [[myWebView stringByEvaluatingJavaScriptFromString:@"document.height"] floatValue];
NSLog(@"NEW HEIGHT %f", height);
[myWebView setBounds:CGRectMake(oldBounds.origin.x, oldBounds.origin.y, oldBounds.size.width, height)];
mainScrollView.contentSize = myWebView.bounds.size;

SOLUTION 3: The last solution is the one that worked for me and it will definitely solve your problem. It involves merging the code in the first two solutions i described. That is you will get the height using javascript as it gives the right height everytime and then use the rest of the code in the first solution and increment few points. Notice i added +125.0, this is how i solved it:

CGFloat height = [[myWebView stringByEvaluatingJavaScriptFromString:@"document.height"] floatValue];
CGFloat width = [[myWebView stringByEvaluatingJavaScriptFromString:@"document.width"] floatValue];
CGRect frame = myWebView.frame;
frame.size.height = height + 125.0;
frame.size.width = width;
myWebView.frame = frame;
mainScrollView.contentSize = myWebView.bounds.size;

Hope this helps!

Jessica
  • 1,508
  • 15
  • 25
1

The WebView loads all its content asynchronously.

you have to wait for webViewDidFinishLoading so the html is loaded (not the image data yet!) Then it knows the size of the html. There sizeToFit should work.

Daij-Djan
  • 49,552
  • 17
  • 113
  • 135
  • this assumes the imgs (and other tags that refer to external resources) have there width=XY and height=XY attributes set! – Daij-Djan Oct 23 '13 at 00:56
  • Can u provide some code in your answer and how to use sizeToFit?? – AJ112 Oct 23 '13 at 09:55
  • @AJ112 Look at the [documentation for `UIView`](https://developer.apple.com/library/ios/documentation/uikit/reference/uiview_class/UIView/UIView.html#//apple_ref/occ/instm/UIView/sizeToFit). If you have `UIWebView* webView`, you can call `[webView sizeToFit]`. – Joshua Gross Oct 28 '13 at 06:54
  • I have the same problem, too, I use [webView sizeToFit] which does not work, Jessica's 3rd solution did work for me. – tomjpsun Jul 29 '15 at 11:51
  • @Daij-Djan how could I access the total height with all images data loaded? – bluenowhere Aug 24 '15 at 03:23
1

Since UIWebView loads in the background, you will have to wait until it loads your page, then figure out the height.

One method is here: https://stackoverflow.com/a/3937599/210171.

However, I usually use the javascript technique. In your web view delegate, change your -webViewDidFinishLoad: to look like this:

- (void)webViewDidFinishLoad:(UIWebView *)webView
{
    NSString * heightString = [webview stringByEvaluatingJavaScriptFromString:@"document.getElementById(\"foo\").offsetHeight;"];
    CGFloat contentHeight = [ heightString doubleValue ] ;
    NSLog( @"contentHeight=%f\n", contentHeight ) ;
}

(This code is taken from https://stackoverflow.com/a/751326/210171)

The height of the content may continue to change as images load if your images don't have their size attribute set. In that case, please see my answer here: https://stackoverflow.com/a/12030878/210171

Community
  • 1
  • 1
nielsbot
  • 15,922
  • 4
  • 48
  • 73
  • a different javascript worked for me but still remains one issue, see my update in the question. Thanks! May be i am doing something wrong after getting the height. See my update – AJ112 Oct 25 '13 at 22:04
  • Are you sure about the positioning of your enclosing scroll view? Try setting `scrollView.backgroundColor = [ UIColor redColor ]` or something like that so you can see where it's positioned. Do the same for your web view: `webView.backgroundColor = [ UIColor orangeColor ]`... – nielsbot Oct 25 '13 at 22:31