Pregunta

When setStatusBarHidden:NO is set before the view loads, the UINavigationBar and other elements appear aligned immediately below the StatusBar as they should. However, when setStatusBarHidden:NO is set after the view loads, the UINavigationBar is partially covered.

The StatusBar must be revealed after loading the said view, but how can this be done without encountering the aforementioned problem?

¿Fue útil?

Solución

I found a hack in a code of mine, though can't remember or find where it came from. The trick is to refresh the navigation bar by hiding and reshowing it:

[self.navigationController setNavigationBarHidden:YES animated:NO];
[self.navigationController setNavigationBarHidden:NO animated:NO];

In my code the function looks like this:

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

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

    [self.navigationController setNavigationBarHidden:YES animated:NO];
    [self.navigationController setNavigationBarHidden:NO animated:NO];
}

However, BE WARNED, this is a hack, and currently I'm struggling with some bugs that appear to originate from this code (navigation item doesn't match navigation content). But since it did work for me in some places, I'd thought I'd mention it.

Edit: I think I found the initial post here: How do I get the navigation bar in a UINavigationController to update its position when the status bar is hidden?

GL, Oded

Otros consejos

(I realise this was an old question, but I just spent half an hour trying to find the answer myself without success, so I thought I would post it here for anyone else who get stuck... especially if you are trying to SHOW the status bar and your view is ending up overlapping it)

I found this works if you want to HIDE the status bar...

[[UIApplication sharedApplication] setStatusBarHidden:YES];
[self.view setFrame: [[UIScreen mainScreen] bounds]];

but not when you want to SHOW the status bar... in that case I use this solution which works, but worries me because it hard codes the status bar height to 20... it also worries me that I have to adjust the view differently depending on orientation. but if I didn't do that it always had the 20 point gap on the wrong edge. In my case I want to turn the status bar off for some views, and then back on when I return. I had particular problems if I rotated the device while the bar was off. so the switch statement, although ugly (someone might post a cleaner solution), works.

[[UIApplication sharedApplication] setStatusBarHidden:NO];

CGRect frame = [[UIScreen mainScreen] bounds];

switch (self.interfaceOrientation) 
{
    case UIInterfaceOrientationPortrait:
        frame.origin.y = 20;
        frame.size.height -= 20;
        break;

    case UIInterfaceOrientationPortraitUpsideDown:
        frame.origin.y = 0;
        frame.size.height -= 20;
        break;

    case UIInterfaceOrientationLandscapeLeft:
        frame.origin.x = 20;
        frame.size.width -= 20;
        break;

    case UIInterfaceOrientationLandscapeRight:
        frame.origin.x = 0;
        frame.size.width -= 20;
        break;

} 

[self.view setFrame:frame];

My guess is the nav bar is being loaded before the status bar is shown, so the position of the nav bar is (0,0) which then overlaps with the status bar at (0,0). You can just move the frame of the navigation bar (or set up an animation block) in viewDidLoad, after you call setStatusBarHidden:NO. Try doing navigationBar.frame = CGRectMake(0,20,320,44); The status bar is 320x20, so just moving your navigation bar down by 20 should accomodate for it.

If you are having this problem because you are not displaying the status bar while your Default.png is loading, and then want to display the status bar immediately upon viewing your first View Controller, just make sure you put [[UIApplication sharedApplication] setStatusBarHidden:NO]; before [self.window makeKeyAndVisible]; in your AppDelegate.m. It happens so quick, you won't ever see the status bar on the splash screen.

[[UIApplication sharedApplication] setStatusBarHidden:NO];
[self.window makeKeyAndVisible];

Here's what I'm doing in my root controller now in iOS 5 after I tell the status bar to animate in. Ugly, but it seems to work.

CGRect rect;

if ( self.interfaceOrientation == UIInterfaceOrientationPortrait )
    rect = CGRectMake(0, 20, 320, 460);
else if ( self.interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown )
    rect = CGRectMake(0, 0, 320, 460);
else if ( self.interfaceOrientation == UIInterfaceOrientationLandscapeLeft )
    rect = CGRectMake(20, 0, 300, 480);
else
    rect = CGRectMake(0, 0, 300, 480);

[UIView animateWithDuration:0.35 animations:^{ self.view.frame = rect; }];

in iOS 7 you can use:

setNeedsStatusBarAppearanceUpdate

for example:

[self.mainViewController.navigationController setNeedsStatusBarAppearanceUpdate];

apple docs:

Call this method if the view controller's status bar attributes, such as hidden/unhidden status or style, change. If you call this method within an animation block, the changes are animated along with the rest of the animation block.

use it only for iOS 7.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top