UIWebView Content Offset

2019-06-07 18:03发布

I want to show a google.maps url into a UIWebView in my app but the page comes up in different point from this that i want. I tried everything of many questions here such as set contentOffset of webview.scrollview or contentInset or scrollsToTop or even with javascript commands but neither of them works.So this is the problem:

wrong

and this is the expected result that i would like to have:

enter image description here

I want my webpage to come up on top and not in the middle.

url: url

1条回答
\"骚年 ilove
2楼-- · 2019-06-07 18:54

This has nothing to do with content offsets etc. - it is the page itself which scrolls down right after it finished loading. When loading the URL in Mobile Safari, you will get the exact same behaviour and can even observe the scrolling animation.

Unfortunately, there is nothing you can do to prevent it, except extracting the scroll code from the html the server delivers before loading it in the webview. This would be tedious and you shouldn't do it anyway, since this will likely break your app once changes are made by google to the inner workings of that page.

The only solution I can think of right now is to scroll the page back to top programmatically after it has scrolled down. I've tried it with the url you provided and it acutally works. To do this, implement webViewDidFinishLoad: in your webview delegate like so:

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

   NSTimer *scrollTimer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(scrollBackToTop) userInfo:nil repeats:NO]; // Better make the timer an ivar

}

and implement a method like:

-(void)scrollBackToTop {

   NSString* javascript = [NSString stringWithFormat:@"window.scrollTo(0, 0);"];
   [theWebView stringByEvaluatingJavaScriptFromString:javascript];

}

This means of course that your webview will first scroll down visibly only to jump back to top, which is rather ugly. So you may want to hide the webview behind an opaque view containing an activity indicator or the like until the webview has loaded and finished all of the scrolling action...

Be aware though that, while less likely and less lethally, this may break as well. When I tried my solution, a 2 second delay was sufficient. If google slows down the animation in the future though, 2 seconds might not be enough and your scrollBackToTop method fires early. Since the java script will not cancel the scroll in progress, it won't scroll back to top at all.

Edit:

Maybe I have something better for you...

Do the following in your webViewDidFinishLoad: method:

NSString* javascript = [NSString stringWithFormat:@"document.getElementById('panel').style.position='fixed'; document.getElementById('panel').style.top='50px';"];
[webView stringByEvaluatingJavaScriptFromString:javascript];

This will completely suppress the scrolling animation. But it comes at a cost: If the user scrolls the webview manually now, the form fields remain fixed in position, while the rest of the page is scrolling normally.

So you need to undo the hack, by doing this:

NSString* javascript = [NSString stringWithFormat:@"document.getElementById('panel').style.position='absolute'; document.getElementById('panel').style.top='0px';"];
[theWebView stringByEvaluatingJavaScriptFromString:javascript];

You need to execute the second step with a delay again, after the scroll script has finished, otherwise the page will do the full scroll. For me, a 1.2 second delay did the trick.

You might want to prevent the user from scrolling during those 1.2 seconds by disabling scrolling on the webviews scrollview until the timer fires.

So there's still room for improvement, but this approach will probably make your app feel more responsive, compared to hiding the webview until it has scrolled back and forth...

查看更多
登录 后发表回答