8

Using this method to hide the status bar:

[[UIApplication sharedApplication] setStatusBarHidden:YES animated:YES];

When setting "hidden" back to NO, the tap-to-scroll-to-top (in UIWebView, UITableView, whatever) doesn't work any more, and requires a restart of the app to get the functionality back.

Is this a bug (I filed a rdar anyhow) or have I missed a step? Should I perhaps expect this behavior since the statusBar "loses touch" somehow with the respective view?

avocade
  • 1,313
  • 1
  • 14
  • 19

9 Answers9

18

You could try setting the ScrollsToTop property to true again after re-showing it:

[currentView setScrollsToTop:YES];

If that's not working, are you definitely only showing one view? If there is more than one scrolling view a scrollViewDidScrollToTop message is ignored...

h4xxr
  • 11,385
  • 1
  • 39
  • 36
  • Very good observation. It's probably getting confused with multiple views. Have to see if I can find a workaround. – avocade Sep 01 '09 at 13:16
  • The problem is that it's a UIWebView that needs to get the scroll-to-top behavior back–and it is not a direct UIScrollView subclass... thus that setScrollsToTop: doesn't work at all. IT probably has a scrollView somewhere in its UIWebViewInternal struct, but that seems to be _very_ opaque. [webView valueForKey:@"_scrollView"] didn't work at all to get direct hold of it. Any other name guesses? :) – avocade Sep 01 '09 at 13:34
  • You could add the UIWebView as a subview of a UIScrollView (in my implementation it is a subview of a UITableView). If it is the only view inside that UIScrollView then calling -setScrollsToTop on the UIScrollView should make it work on the UIWebView... – h4xxr Sep 01 '09 at 13:51
  • Your name really is h4x0r, isn't it :) – avocade Sep 02 '09 at 08:43
  • +1 for those who uses a UIScrollView combined with a UIPageViewController like me. You should remove it from superview in viewDidDisappered and add it again in viewWillAppear. – onnlv Jan 14 '14 at 19:03
10

In iOS 5.0 you can access the scrollview property of the UIWebView

webView.scrollView.scrollsToTop = YES;
Paul Cooper
  • 357
  • 3
  • 12
7

The following fix by Alex worked for me. Thanks!

((UIScrollView *)[[webView subviews] objectAtIndex:0]).scrollsToTop = NO;

Being in a hurry this fix worked great, however given more time I might've subclassed the UIWebView and accessed the protected UIScrollView member directly.

The worry I have with Alex' method is that it assumes that UIScrollView is at index zero of the subviews (encapsulation allows private members to change). Which suggests another solution still:

for (UIView* v in [webView subviews])
{
    if ([v isKindOfClass:[UIScrollView class]])
    {
        (UIScrollView *)v.scrollsToTop = NO;
    }
}
Maulik
  • 19,348
  • 14
  • 82
  • 137
user305578
  • 71
  • 1
  • 2
5

You can use the following code to have the UIWebView ignore scrollToTop without the extra UIScrollView:

((UIScrollView *)[[webView valueForKey:@"_internal"] valueForKey:@"scroller"]).scrollsToTop = NO;
Maulik
  • 19,348
  • 14
  • 82
  • 137
Nick Toumpelis
  • 2,717
  • 22
  • 38
  • 4
    As this uses a private API call, this will likely cause your application to be rejected. You may be able to get away with `((UIScrollView *)[[webView subviews] objectAtIndex:0]).scrollsToTop = NO;` – Alex Reynolds Dec 23 '09 at 00:31
  • Thanks Alex! Much more elegant and safe for sure. – Nick Toumpelis Dec 23 '09 at 07:59
5

I was having a similar problem where the scroll-to-top functionality was lost. Turns out this will only work when you have only one active view at a time (within the same scroll view). In my case I had a table view and another view which would fade in/out. Adding a removeFromSuperview at the end of the animation did the trick.

The answer was in the UIScrollView.h file comments:

/*
 this is for the scroll to top gesture. by default, a single scroll visible scroll view with this flag set will get the call. if there is more than one visible with this
 flag set or the delegeat method returns NO, the view isn't scrolled 
 */
@property(nonatomic) BOOL  scrollsToTop;          // default is YES. if set, special gesture will scroll to top of view after consulting delegate
Juan
  • 1,428
  • 2
  • 22
  • 30
3

I had a similar problem after playing a Youtube video within my app. scrollsToTop was still set to YES but tapping the status bar had no effect.

I finally realised that my app window was no longer the key window. After adding the following line to a UIWindow subclass (which I already had for other reasons) everything worked as it should again:

if (![self isKeyWindow]) [self makeKeyWindow];
prendio2
  • 1,885
  • 17
  • 25
0

When there are multiple scrollview, you can also set scrollUpToTop to NO for the others scrollview. cf:

setScrollsToTop with multiple UIScrollView classes and/or subclasses(UITableView)

Community
  • 1
  • 1
lansher1985
  • 179
  • 1
  • 13
0

I just ran across a similar behavior in the app I'm currently working on. In its case, if you load a YouTube video from within a UIWebView, scroll to top stops working for the rest of the application's life cycle. I kind of assume this might happen after loading the movie player as well, but haven't confirmed. That functionality has been around a lot longer and probably has fewer bugs.

Ben Lachman
  • 3,083
  • 1
  • 28
  • 44
0

I want to add my case, I add an UIWebView on an UIScrollView, as h4xxr had answered on the top:

If there is more than one scrolling view a scrollViewDidScrollToTop message is ignored

So, I get a simply way to make it work on webView: just set the scrollView·s scrollsToTop property false.

And when tap the status bar, it won`t got intercepted by the scrollView, and the webView scrolls to the top!

    UIScrollView *scrollView = [[UIScrollView alloc] init];
    scrollView.frame = self.view.bounds;
    scrollView.scrollsToTop = false; //igore scrollView`s scrollsToTop
    [self.view addSubview:scrollView];

    UIWebView *webView = [[UIWebView alloc] init];
    webView.frame = scrollView.bounds;
    [scrollView addSubview:webView];
MichaelMao
  • 528
  • 6
  • 15