jcrowson
jcrowson

Reputation: 4290

Hiding status bar after view has loaded leaves black bar

I'm running into a bit of a weird problem when hiding the status bar after the view had loaded. If I add the following method in the ViewDidLoad method, the status bar is completely removed from the view:

[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationSlide];

However, if I call this method in an IBAction or another method, the status bar still slides away but leaves a black bar the same height as itself behind.

I've thought about shifting the entire view up by 20px but is this really a fix? I don't want to just overlap a black bar incase the status bar height changes in future OS upgrades.

Status bar leaving black bar

Upvotes: 4

Views: 1561

Answers (5)

Alex Koshy
Alex Koshy

Reputation: 1661

I was able to fix this issue by calling:

[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationSlide];

as others recommended before presenting the view controller that is displaying the black bar.

For example, if I had an action that presented ViewController, I would call it like so:

- (IBAction)presentViewController:(id)sender {
    [[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationSlide];
    ViewController *vc = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil];
    [self presentViewController:vc animated:YES completion:nil];
}

Upvotes: 0

bernytech
bernytech

Reputation: 11

In viewWillAppear:

[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationFade];

In viewDidAppear, you can insert:

self.view.window.rootViewController.view.frame = [UIScreen mainScreen].applicationFrame;

In viewWillDisappear:

[[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationFade];

Upvotes: 0

NJones
NJones

Reputation: 27157

Hard-coding any number is always counter to future proofing. Your concerns are correct. There is a bit of a trick to properly handling the hiding of the statusBar. But all the needed information is available.

For example the UIApplication singleton has a property named statusBarFrame which is precisely what it sounds like, a CGRect of the statusBar's frame. The cool thing is that once you have called setStatusBarHidden:withAnimation: that property will give you the new frame, even before the animation completes. So really you are simply left with some basic math to adjust the view's frame.

In short your gut feeling is correct; always compute things live.

I've had good success with a category method like this. (Even when toggling in-call status bar in simulator(Command - T)):

@implementation UIApplication (nj_SmartStatusBar)
// Always designate your custom methods by prefix.
-(void)nj_setStatusBarHidden:(BOOL)hidden withAnimation:(UIStatusBarAnimation)animation{
    UIWindow *window = [self.windows objectAtIndex:0];
    UIViewController *rootViewController = window.rootViewController;
    UIView *view = rootViewController.view;

    // slight optimization to avoid unnecassary calls.
    BOOL isHiddenNow = self.statusBarHidden;
    if (hidden == isHiddenNow) return;

    // Hide/Unhide the status bar
    [self setStatusBarHidden:hidden withAnimation:animation];

    // Get statusBar's frame
    CGRect statusBarFrame = self.statusBarFrame;
    // Establish a baseline frame.
    CGRect newViewFrame = window.bounds;

    // Check if statusBar's frame is worth dodging.
    if (!CGRectEqualToRect(statusBarFrame, CGRectZero)){
        UIInterfaceOrientation currentOrientation = rootViewController.interfaceOrientation;
        if (UIInterfaceOrientationIsPortrait(currentOrientation)){
            // If portrait we need to shrink height
            newViewFrame.size.height -= statusBarFrame.size.height;
            if (currentOrientation == UIInterfaceOrientationPortrait){
                // If not upside-down move down the origin.
                newViewFrame.origin.y += statusBarFrame.size.height;
            }
        } else { // Is landscape / Slightly trickier.
            // For portrait we shink width (for status bar on side of window)
            newViewFrame.size.width -= statusBarFrame.size.width;
            if (currentOrientation == UIInterfaceOrientationLandscapeLeft){
                // If the status bar is on the left side of the window we move the origin over.
                newViewFrame.origin.x += statusBarFrame.size.width;
            }
        }
    }
    // Animate... Play with duration later...
    [UIView animateWithDuration:0.35 animations:^{
        view.frame = newViewFrame;
    }];
}
@end

Upvotes: 3

WolfLink
WolfLink

Reputation: 3317

Yes, moving the view 20 pixels should fix your problem. The black is absence of anything to display, not an actual black bar.

As for potential status height changes, this fix will not work if that happens because the view will be moved by the height of the new status bar. If that happens, you will have to either add different offsets for different status bars, or find a completely new solution.

Upvotes: 0

christo16
christo16

Reputation: 4843

Why are you calling this in viewDidLoad?

Try it in loadView?

- (void)loadView {
    [super loadView];

    [[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationSlide];
}

Upvotes: 0

Related Questions