Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS UIWebView inside a UIScrollView

I want to have a UIWebView inside a UIScrollView. The UIWebView will sometimes go out of bounds of the iPhone screen so I need a way to scroll the view so I can see all the content (but I don't want to use the built in scrolling of the UIWebView). So I'm thinking of putting all the content inside of a UIScrollView and then making the height of the UIScrollView to equal the height of the UIWebView and other views that are in it.

Here's an image to help describing my problem:

Interface Builder Image

like image 973
Peter Warbo Avatar asked Jun 22 '11 13:06

Peter Warbo


1 Answers

I did exactly the same thing. Here's how I made it work:

  1. Add the UIWebView as a subview of the UIScrollView (obviously ;-)
  2. Disable the native scrolling of the UIWebView (you can do that by iterating through the subviews of the UIWebView until you find it's UIScrollView and set scrollEnabled = NO on it.
  3. Set the contentSize of your UIScrollView and the UIWebView's frame to the size of the UIWebViews HTML content.

The last point is bit tricky because you cannot be sure that the HTML is completely rendered when webViewDidFinishLoad: gets called on the UIWebViewDelegate.

Here's a reliable way to get the HTML content size:

1.Add a javascript function to the HTML that gets called when the HTML Document is ready:

window.onload = function() {
    window.location.href = "ready://" + document.body.offsetHeight;
}

This functions sends a request that has the content height in it's URL.

2.In your UIWebViewDelegate you intercept this request:

- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType {
        NSURL *url = [request URL];
        if (navigationType == UIWebViewNavigationTypeOther) {
           if ([[url scheme] isEqualToString:@"ready"]) {
               float contentHeight = [[url host] floatValue];
               yourScrollView.contentSize = CGSizeMake(yourScrollView.frame.size.width, contentHeight + yourWebView.frame.origin.y);
               CGRect fr = yourWebView.frame;
               fr.size = CGSizeMake(yourWebView.frame.size.width, contentHeight);
               yourWebView.frame = fr;

               return NO;       
        }

        return YES;
}

Hope that helps

UPDATE

Here is the Swift 2 version:

func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {
    guard navigationType == .Other else { return true }
    if let url = request.URL, let host = url.host {
        guard url.scheme == "ready" else { return true }
        if let contentHeight = Float(host) {
            yourScrollView.contentSize = CGSizeMake(yourScrollView.bounds.size.width, CGFloat(contentHeight))
            var fr = webView.frame
            fr.size = CGSizeMake(fr.size.width, CGFloat(contentHeight))
            webView.frame = fr
        }

        return false
    }

    return true
}
like image 65
joern Avatar answered Nov 16 '22 00:11

joern