6
votes

I have two view controller. One scrollview for page control and one for detail (scroll vertical).

When i click status bar on iPhone the scrollToTop not working, and in iPad the scrollToTop is working.

I am sure that the scrollView.scrollToTop is YES. because i already print it.

Anyone know what cause the iPhone scrollToTop not working?

Thank you

Edit: I try by calling the scrollView delegate. in iPad this delegate its called. - (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView

in iPhone it is not called. I already use both contentScrollView.delegate = self; But the iphone not working :(

Edit: Try subclassing UIWindow (not working)

Window.h

#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
@interface Window : UIWindow
@end

Window.m

 #import "Window.h"

 @implementation Window

 - (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
if ([event type] == UIEventTypeTouches && point.y < 250) {
    //Send Your Notification Here
    NSLog(@"KAROOO");
}
NSLog(@"HELLOWW");
return [super hitTest:point withEvent:event];
}
@end

AppDelegate.h

@property (nonatomic, strong) IBOutlet Window *window;

AppDelegate.m

@synthesize window = _window;
4

4 Answers

3
votes

From what I understand you have 2 UIScrollViews simultaneously on screen.

From what I have seen & experienced, On iOS 4 having 2 UIScrollViews side by side gives undefined behaviour. One of the scrollview may scroll, sometimes other, sometimes neither.

On iOS 5 if you have 2 UIScrollViews side by side then tapping on status bar "scrolls to top" the UIScrollView right "under your tap"

I don't know how this works, but this has been my observation. iOS 5 is smart !!

If your UIScrollViews are one above other then probably the behaviour is undefined. I haven't checked.

Hope this helps.

If you want to get it working anyways then here is a possible solution.

Subclass or Add a category on UIWindow and add a gesture recognizer / or implement hitTest that detects tap only for Y < 20 and so on and then have it send a notification and listen to this in your viewController and programmatically scroll the UIScrollView to top.

EDIT

Implement this in the UIWindow subclass (iPad)

- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    if ([event type] == UIEventTypeTouches && point.y < 20 && [[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationPortrait) {
        NSLog(@"Portrait");
    } else if ([event type] == UIEventTypeTouches && point.y > 1004 && [[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationPortraitUpsideDown) {
        NSLog(@"PortraitUpsideDown");
    } else if ([event type] == UIEventTypeTouches && point.x < 20 && [[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationLandscapeLeft) {
        NSLog(@"LandscapeLeft");
    } else if ([event type] == UIEventTypeTouches && point.x > 748 && [[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationLandscapeRight) {
        NSLog(@"LandscapeRight");
    }
    return [super hitTest:point withEvent:event];
}
1
votes

In case you have more then one UIScrollView instance (including subclasses e.g. UITableView e.t.c) on the same screen you need to define wich one should act on scrollToTop event. That means, that you need to go through those instances and set their scrollToTop property to NO except for the one you do want to do so. For me it worked always. In case it didn't, it was because of some other UIScrollView that I didn't knew it's there. In that case I just walked throug all subviews recursively disabling thet property and then it started to work as espected. Cheers. :)

1
votes

Don't know what Apple were smoking but by design, the behaviour on iPhone is distinctly different from iPad. Apple's documentation does include a "Special Condsideration" note as follows...

On iPhone, the scroll-to-top gesture has no effect if there is more than one scroll view on-screen that has scrollsToTop set to YES.

So on iPhone you have to ensure that there is only ever one UIScrollView (or UITableView/UICollectionView/UIWebView etc) that has its scrollsToTop = YES.

Since scrollsToTop defaults to YES you have to explicitly set scrollsToTop = NO for the UIScrollView's you do not want to scroll when the user taps the status bar.

0
votes

Here is my solution based on NSIntegerMax's answer. This way we don't have to care about the orientation or have hardcoded values.

declare this macro

#define isInStatusBar(frame, point) (point.x >= frame.origin.x && point.x <= (frame.origin.x+frame.size.width) && point.y >= frame.origin.y && point.y <= (frame.origin.y+frame.size.height))

and implement the method:

- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    CGRect frame = [[UIApplication sharedApplication] statusBarFrame];

    if ([event type] == UIEventTypeTouches && isInStatusBar(frame, point)) {
        [[NSNotificationCenter defaultCenter] postNotificationName:kNotificationAppDidTouchStatusBar object:nil];
    }

    return [super hitTest:point withEvent:event];
}