2

I have a UIWindow with windowLevel set to UIWindowLevelStatusBar+1. This window has a single semi-transparent view that blocks the status bar. I need to sometimes pass touch events from the view on to the status bar. Any ideas?

unexpectedvalue
  • 6,079
  • 3
  • 38
  • 62
  • I wonder how VoiceOver is going to tell the time, signal and battery level then. I know a VoiceOver user and he cannot use about 70% of all apps since they are written by lazy developers who don't care about their users. :/ –  Mar 27 '11 at 10:26
  • That isn't a problem, the view is semi-transparent and most of the time should receive events. That what the question is for. – unexpectedvalue Mar 27 '11 at 10:30
  • 1
    @ssteinberg when VoiceOver is enabled, a double tap is a tap, and a single tap selects something and speaks it. If your view overlaps the status bar, no items will ever be selected on it. –  Mar 27 '11 at 10:48
  • Again, that is where my question comes in, most of the time I want touch events to be passed on to the status bar, as if nothing is there. Sometimes I need to intercept them. Just hiding the view isn't an option. – unexpectedvalue Mar 27 '11 at 10:51
  • 2
    You app will probably be refused entry to the App Store for blocking/overlaying the status bar. – Jonathan. Mar 27 '11 at 11:28

3 Answers3

4

So, it seems to be doable with a custom subclass of UIWindow overriding hitTest:withEvent: that manually detects a touch in the subview, and always returns nil.

- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    if ([event type]==UIEventTypeTouches) {
        UIView *v=[super hitTest:point withEvent:event];
        if (customSubViewthatCoversStatusBarOnly==v) 
            //doLotsOfCoolStuff
    }

    return nil;
}

Status bar recognizes all touches, so there is no breakage with scroll-to-top, return to call, VoiceOver, etc.. And I still get to intercept taps on statusbar.

I hacked this up just now. I will probably upload an update to App Store later this week with a more mature version of this, will see how much complaining Apple will do.

EDIT - 7th April:
Was approved by Apple. Works flawlessly.

unexpectedvalue
  • 6,079
  • 3
  • 38
  • 62
2

You might find this component over on github helpful.

Otherwise, Cocoa with Love blog post is really useful to read perhaps.

petert
  • 6,672
  • 3
  • 38
  • 46
  • Thanks. The Cocoa post is outdate, and intercepting touches is simple. Intercepting and passing on to status bar is the problem. This MTStatusBar, looks interesting but it actively blocks the status bar, that doesn't look like something Apple will like. – unexpectedvalue Mar 27 '11 at 11:42
  • Sure. If you're after the sort of behaviour that the Reeder app has, where it only overlays a small part of the status bar during updates, this MTStatusBar might be a coding start? – petert Mar 27 '11 at 11:52
1

As far as I understand this, you should use - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event to implement that behavior. Basically, you either return self if you want to handle the touch event or [super hitTest:point withEvent:event] to let the status bar handle the touch event.

Check out the UIView Class Reference for more.

EDIT: As Jonathan mentioned, Apple might not approve this.

ryyst
  • 9,563
  • 18
  • 70
  • 97