Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIScrollView + UIWebView = NO scrollsToTop

It looks like a problem which could have simple solution, but I haven't found anything what could lead the way to it. I'm using UIWebView inside of UIScrollView and tapping on statusBar (to scroll content to top) is not working.

I've made simple test application to see if it's really UIWebViews fault. And it really is.

//  scrolls to top on status bar tap 
UIScrollView *sv = [[UIScrollView alloc] init];
sv.frame = CGRectMake(0, 0, 320, 480);
sv.contentSize = CGSizeMake(320, 1200);
[self.view addSubview:sv];

// doesn't scroll
UIScrollView *sv = [[UIScrollView alloc] init];
sv.frame = CGRectMake(0, 0, 320, 480);
sv.contentSize = CGSizeMake(320, 1200);

UIWebView *wv = [[UIWebView alloc] init];
wv.frame = CGRectMake(0, 0, 320, 100);
[sv addSubview:wv]; 

[self.view addSubview:sv];

So, I think maybe there's something I could disable to make UIWebView not to mess with scrollToTop? Or some kind of workaround also would be nice.

Any ideas?

like image 326
sniurkst Avatar asked Feb 01 '10 07:02

sniurkst


2 Answers

I ran into this last night until I finally found the answer buried in a comment to a comment. The idea of that original post is that when you add the UIWebView to your UIScrollingView, you use the following:

- (void) ensureScrollsToTop: (UIView*) ensureView {
    ((UIScrollView *)[[webView subviews] objectAtIndex:0]).scrollsToTop = NO;
}

This seemed fishy to me since the first sub-view of a UIWebView claims to be a UIScroller which is not a subclass of UIScrollView. However, since UIScroller supports the scrollsToTop property, the cast just gives us a way past the compiler warning:

Class List:
    Class = UIScroller
    Class = UIView
    Class = UIResponder
    Class = NSObject
Supported Methods:
    ...
    Method _scrollToTop
    Method setScrollsToTop:
    Method scrollsToTop
    ...
Supported Properties:
    Property scrollsToTop

EDIT: Just another quick note about where this actually needs to occur: in the webViewDidFinishLoad callback. Calling it on UIWebView construction isn't good enough because at that time the UIWebView hasn't created it's child views yet, which are the ones causing the problem:

- (void)webViewDidFinishLoad:(UIWebView *) wv {    
    [self ensureScrollsToTop: wv];
}

EDIT #2:

now, in iOS 5, as noted in iPhone OS: Tap status bar to scroll to top doesn't work after remove/add back use UIWebView's new @property scrollView, making ensureScrollsToTop implementation unnecessary for projects that aren't using deployment targets lower than iOS 5.0 .

like image 124
nivekastoreth Avatar answered Nov 12 '22 21:11

nivekastoreth


In iPhone OS, if there is more than one UIScrollView (or its subclass, for example UITableView, UIWebView) in the current viewController, the system doesn't know which UIScrollView should be scrolled to the top.

Quick fix: for all the UIScrollViews that you don't want to support scrollsToTop, just set the scrollsToTop as NO, then every thing works perfect.

self.scrollView1.scrollsToTop = NO;
self.scrollView2.scrollsToTop = NO;
self.scrollView1.scrollsToTop = YES; // by default scrollsToTop is set as YES, this line is not necessary
like image 24
flypig Avatar answered Nov 12 '22 22:11

flypig