Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS7 UIWebView has wrong scrollview inset on inital load

Whenever I display a PDF file in my webView it looks like it's initial scrollview inset is not set correctly but as soon as I start scrolling or zooming, it jumps to it's correct place :/

The PDF is loaded but it's partially under the navigation bar The PDF is loaded but it's partially under the navigation bar

As soon as I start scrolling or zooming in, it snaps to it's intended default position As soon as I start scrolling or zooming in, it snaps to it's intended default position

If I load PNGs into the same webview they have the perfect inset and are displayed right under the navigation bar (not a line of black pixels in between).

Does anyone know how I can solve this?

Some of the webView settings:

webView.clipsToBounds = NO;
webView.scalesPageToFit = YES;
like image 534
budiDino Avatar asked Jul 30 '14 15:07

budiDino


2 Answers

I implemented this workaround:

- (void)webViewDidFinishLoad:(UIWebView *)aWebView {

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.15 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        self.webView.scrollView.contentOffset = CGPointMake(0, -(self.webView.scrollView.contentInset.top));
    });

}

It "jumps" a bit when the WebView is loaded, but at least the contentOffset is set correctly. You might also need to fine tune the delay (0.15 ms in this example).

like image 118
Klemens Zleptnig Avatar answered Nov 16 '22 02:11

Klemens Zleptnig


I ran into this same problem; very annoying. I was able to resolve it by first making my WebViewController a UIScrollViewDelegate.

@interface WebViewController () <UIWebViewDelegate, UIScrollViewDelegate>

When I added some debug in the scrollViewDidScroll delegate to inspect some properties and see what was going on, I was able to observe the framework readjust my content offset to be CGPointZero (which causes it to go behind the navigation bar). By checking for that condition, you can basically nullify the effect by resetting it immediately.

So once the UIWebView finished loading, I calculate the actual inset that I need based on the height of the navigation bar and the status bar.

- (void)webViewDidFinishLoad:(UIWebView *)webView {
    webView.scrollView.delegate = self;
    float inset = self.navigationController.navigationBar.bounds.size.height +
        [UIApplication sharedApplication].statusBarFrame.size.height;
    webView.scrollView.contentInset = UIEdgeInsetsMake(inset, 0.0, 0.0, 0.0);
}

Then whenever I detect a scroll, I just prevent the offset from canceling out my contentInset. I excluded this effect from when the user was zoomed so the document didn't jump around if the user happened to land on this boundary.

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    if(scrollView.contentOffset.y == 0 && !scrollView.zooming)
        [scrollView setContentOffset:CGPointMake(0.0, -(scrollView.contentInset.top))];
}

The advantage here is that you don't need to depend on any timing elements, and you don't see the PDF jump around when the dispatch executes. The actual contentInset you need is also dynamically determined.

like image 2
Kyle Avatar answered Nov 16 '22 02:11

Kyle