UIWebView Content Offset - ios

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:
and this is the expected result that i would like to have:
I want my webpage to come up on top and not in the middle.
url: url

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...

Related

When WKWebView displays content, it will be white for about 1~2 second

When WKWebView displays content, it will be white for about 1~2 second. Not a memory problem, I use [self loadHTMLString:string baseURL:baseURL]; show the HTML content, but each time need to wait 1~2 second will be normal display. UIWebview does not have this problem.
Is there any way to solve it? Or optimize this blank time?
Sometimes it takes a while to load a page over the network. The page is white until the data can be loaded. A simple solution is to issue your load() command early. Before it needs to be called. I anticipate the next page, but don't display it until it is needed. When it is needed, it is already loaded, I just need to add it:
viewController.view.addSubview(webView)
I use two different methods, depending on my needs: I either load the view early and change the alpha to 0 so it is invisible:
webView.alpha = 0
Of course, I change it to 1.0 when I want it to display.
Or I remove the web view from the superview (it needs to be a class property so it is retained), like this:
func removeWebView(_: UITapGestureRecognizer) {
print("removewebview tap")
webView.removeFromSuperview()
}
If you follow this approach, you will need to call a method that adds the subview (web view) back, and if you are using auto layout, you need to reapply constraints because they are lost when you remove the web view from the superview. If you do that, don't forget to call .setNeedsLayout() on the parent view.

SVPullToRefresh - Refresh view does not show

Sorry if my question seems stupid but I've been trying everything to get it to work for several days now and nothing comes to my mind anymore.
I'm trying to use SVPullToRefresh on a UIScrollView which is, in my storyboard, fixed to the main view of my View Controller (space constraints to superview 0,0,0,0).
Code is pretty straightforward :
__weak ALExploreViewController *weakSelf = self;
[self.globalScrollView addPullToRefreshWithActionHandler:^{
[weakSelf refreshData];
}];
[self.globalScrollView triggerPullToRefresh];
The thing is, when I launch the app, the pull to refresh appears as I triggered it in code. Then I make it disappear when my data are updated (self.globalScrollView.showsPullToRefresh = NO;). And then when I scroll up to refresh, the "pull to refresh" view won't show. If I deactivate bouncing, the view won't event scroll upper than y=0, and if I activate it, it bounces but no sign of the P2R view.
Any ideas ? Please ?
You should not use self.globalScrollView.showsPullToRefresh = NO;, this is used to disable the refreshView.
When your data is updated, you can call
- (void)stopAnimating;
Try it!

Interrupting UIScrollView Bounce after it has started?

I have a UIWebView that loads a new request when the user scrolls a set distance past the end, or before the beginning of the content (ie. into the area that "bounces" back), via the scrollView delegate
Unfortunately, I have found that once the bounce animation starts, it has to complete, and completely bounce back to the edge of the content area, before the UIWebView will display the new content that it has loaded.
Is there any way to interrupt this, and have it not need to bounce back before displaying the new content? I would prefer for the old content just to disappear without needing to bounce all the way back to its edge . Either that, or speed up the animation.
Things to note:
I do NOT want to turn off bouncing.
I have tried importing quartzcore and using -removeAllAnimations on every view I can think of, including the superview, and it doesn't help.
I have tested it, and it is not because of latency in the loading of the request that is causing the delay in displaying the new content.
There are a few UIViewAnimationOptions that look like they could be helpful, but I can't see where I would use them, and I don't really want to subclass UIWebview if I can help it.
Any ideas?
thanks in advance

How to programmatically simulate a double-tap on a UIWebView?

My app has a UIWebView that displays HTML emails. If I zoom in on the content and then double-tap on it a couple of times, the email content eventually gets resized so that it all fits on the screen again.
I'd like to programmatically reproduce this resizing behavior (I want to be able to call a function that re-scales the content so that it all fits on the screen); calling sizeToFit on the web view does not seem to have any effect.
If you know the CGRect you want to scale it to, then you can use,
- (void)zoomToRect:(CGRect)rect animated:(BOOL)animated
As UIWebView is scrollable, So I guess you should be able to do this.
Apparently your UIWebView should have an iVar named scrollView. So, if your UIWebView object name is webView. just do something like, below code might not be 100% syntactically correct. But you must have got the idea.
[webView.scrollView zoomToRect:CGMakeRect(0,0,0,0) animated:YES];

UIWebView's sizeToFit works only once

In my custom UIViewController I have two distinct UIWebViews for which my custom UIViewController is the delegate. In webViewDidFinishLoad:webView I call [webView sizeToFit] and I can confirm it gets called twice, one for each UIWebView. However, to my great dismay, it only seems to affect the first one that gets called, while the other one remains unchanged. Obviously both their contents exceed the bounds, so I expect them to be resized accordingly.
Now, after lots of hours spent on this issue, how am I even supposed to proceed to understand what's wrong?
EDIT: Alright, apparently the problem is that the view in which I put the second UIWebView is not visible on the screen when I call sizeToFit. Calling it with a delay after the view is shown results in the expected behaviour. Now I have to find a way to do this without showing it, because I need to to be visible at a later time. Ideas?
It seems that doing that on viewDidAppear works like a charm.

Resources