ScrollOffset in UIWebView?
Asked Answered
C

7

9

I'm having a really hard time understanding delegates and object inheritance (if I may use this word) and I think I need a simple (or so I think) thing: catch scrollViewDidScroll event in UIWebView and get offset (basically, just to know if scroll is not on top/bottom, so I could hide navigation and tab bars).

Is there any way I could do it? I already using UIWebviewDelegate in my view controller to "shouldStartLoadWithRequest". Maybe I could some how use UIScrollViewDelegate too for scrollViewDidScroll? If yes, then how?

I really have trouble understanding delegates. I've red some articles, but still, in practice, I can't manage to use them.

Any help or info would be lovely.

Thank you in advance!

Contain answered 22/10, 2009 at 3:1 Comment(0)
O
2

There is a scrolling view in the UIWebView, but it a) isn't a UIScrollView, and b) is something Apple considers a private implementation detail (and you should too). I only really have two suggestions:

  1. File a bug with Apple asking them to expose more of the infrastructure of the web view, or at least add some more delegate methods by which we can be notified of these sorts of events.
  2. Add some JavaScript code to your page that listens from scroll events, and notifies your app of them.

The basic foundation of #2 is to load a fake URL, and have your web view delegate process (and abort!) that load. (This question has come up a few times here on Stack Overflow.)

UPDATE:

As of iOS 5, there is now a public scrollView property on UIWebView that you can use to customize scrolling behavior. The exact view hierarchy of the web view remains an undocumented implementation detail, but this gives you a sanctioned way to access this piece of it.

Optative answered 22/10, 2009 at 4:0 Comment(3)
Thanks, for now I've ended up with different interface solutions for what I needed to do. So, there is no way one could access UIWebViews UIScroller and extract some offsets from it?Contain
No documented/safe way, no. I'm sure that if you poke around in the UIWebView's view hierarchy with a debugger, you can probably come up with something, but it may break at any time. And Apple doesn't like undocumented APIs in the App Store. (OTOH, the JavaScript APIs inside the web view are well-documented and stable....)Optative
It is an UIScrollView and you can set the delegate. There is not a bug. You assign it to the subview and implement the ScrollViewDelegate.Closegrained
S
13

To retrieve scroll events on UIWebView I personnaly use this code to get the scrollview that is inside the UIWebView :

- (void) addScrollViewListener
{
    UIScrollView* currentScrollView;
    for (UIView* subView in self.myWebView.subviews) {
        if ([subView isKindOfClass:[UIScrollView class]]) {
            currentScrollView = (UIScrollView*)subView;
            currentScrollView.delegate = self;
        }
    }
}

It's working. You can also use it to call [currentScrollView setContentOffset:offSet animated:YES]; The only problem may be not to pass Apple code checking. I don't know yet since I'm still in coding phase.

[UPDATE] The app with this code is in the app store for 4 months now and used by 40 000 users. I didn't have any trouble [UPDATE]

Seena answered 3/11, 2010 at 11:0 Comment(4)
I can't see why this wouldn't pass: what's non-public API's are being used?Astral
It's just a bit ugly to get the scrollview like this. Apple would have given a scrollView property on the webview if they wanted us to use it I think. But yeah, my app has been approved.Seena
I would assume the scrollview already has a delegate set... or may in a future iOS version. Does this not seem to be the case?Antakiya
@Antakiya I'm using this code for a while and I didn't see any side effect yet. I'd say it's sure... but yeah future iOS could change things.Seena
L
7

You can use the following methods to solve your problem.

For getting the pageOffset:

int pageYOffset = [[webViewObj stringByEvaluatingJavaScriptFromString:@"window.pageYOffset"] intValue];

For getting the total scroll height of a webpage:

int scrollHeight = [[webViewObj stringByEvaluatingJavaScriptFromString:@"document.documentElement.scrollHeight"] intValue];

For scrolling the webpage to a particular offset:

[webViewObj stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"document.body.scrollTop = %d",scrollHeight ]];

Leith answered 2/6, 2010 at 17:59 Comment(0)
H
4

I made a modification to detect the class with isKindOfClass. Works - but may have issues with Apple code checking as stated above.

UIScrollView* currentScrollView;
for (UIView* subView in terms.subviews) {
    if ([subView isKindOfClass:[UIScrollView class]]) {
        NSLog(@"found scroll view");
        currentScrollView = (UIScrollView *)subView;
        currentScrollView.delegate = self;
    }
}
Hydric answered 17/11, 2010 at 17:38 Comment(0)
M
4

Old thread, I know -

As of iOS 5.0 you can use

myAccountWebView.scrollview

to access content size and offset.

Mesonephros answered 14/11, 2012 at 2:1 Comment(0)
O
2

There is a scrolling view in the UIWebView, but it a) isn't a UIScrollView, and b) is something Apple considers a private implementation detail (and you should too). I only really have two suggestions:

  1. File a bug with Apple asking them to expose more of the infrastructure of the web view, or at least add some more delegate methods by which we can be notified of these sorts of events.
  2. Add some JavaScript code to your page that listens from scroll events, and notifies your app of them.

The basic foundation of #2 is to load a fake URL, and have your web view delegate process (and abort!) that load. (This question has come up a few times here on Stack Overflow.)

UPDATE:

As of iOS 5, there is now a public scrollView property on UIWebView that you can use to customize scrolling behavior. The exact view hierarchy of the web view remains an undocumented implementation detail, but this gives you a sanctioned way to access this piece of it.

Optative answered 22/10, 2009 at 4:0 Comment(3)
Thanks, for now I've ended up with different interface solutions for what I needed to do. So, there is no way one could access UIWebViews UIScroller and extract some offsets from it?Contain
No documented/safe way, no. I'm sure that if you poke around in the UIWebView's view hierarchy with a debugger, you can probably come up with something, but it may break at any time. And Apple doesn't like undocumented APIs in the App Store. (OTOH, the JavaScript APIs inside the web view are well-documented and stable....)Optative
It is an UIScrollView and you can set the delegate. There is not a bug. You assign it to the subview and implement the ScrollViewDelegate.Closegrained
N
1

It's a good question. UIWebView is not a subclass of UIScrollView, although I can see why one might think it is. That means using the UIScrollViewDelegate methods is not an option to do what you want, and the UIWebViewDelegate protocol does not respond to those scrolling event type of messages. I don't think there's an easy way to detect scrolling events in a web view.

Nickelplate answered 22/10, 2009 at 3:27 Comment(0)
S
1

I tired the delegate method and found it prevented the view from scrolling when the keyboard was shown. I found that by adding an observer you do not override the current delegate and will prevent you from effecting the webview performance.

for (UIView* subView in myAccountWebView.subviews) {
    if ([subView isKindOfClass:[UIScrollView class]]) 
    {
        NSLog(@"found scroll view");
        [((UIScrollView*)subView) addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew context:nil];
    }
}
Shoran answered 23/6, 2011 at 15:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.