Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I get the navigation bar in a UINavigationController to update its position when the status bar is hidden?

Tags:

iphone

I have a UINavigationController with a visible Navigation Bar. I have one particular UIViewController which I'd like to hide the status bar when pushed into the navigation stack. Once this viewController is popped I'd like to show the status bar again.

I'm hiding the bar in the viewWillAppear method of my UIViewController like this:

- (void) viewWillAppear:(BOOL)animated {

    [super viewWillAppear:animated];

    [self.navigationController setWantsFullScreenLayout:YES];
    [[UIApplication sharedApplication] setStatusBarHidden:YES animated:YES];    
}

Note that I'm setting setWantsFullScreenLayout:YES here for clarity, but I'm actually just setting this property in Interface Builder.

The problem: The navigation bar of the NavigationController doesn't move up to take the space of the now hidden status bar.

A hacky solution The only thing I found that worked to refresh the position of the nav bar was to hide it and show it again, like this:

[[UIApplication sharedApplication] setStatusBarHidden:YES animated:YES];
[self.navigationController setNavigationBarHidden:YES animated:NO];
[self.navigationController setNavigationBarHidden:NO animated:NO];

but this is clearly a hack, there has got to be a better way.

Other things I tried:

  1. I tried calling the [super viewWillAppear] after hiding the status bar, i.e. at the end of my method.

  2. I tried setNeedsLayout on the navigationController.view like this:

    [[UIApplication sharedApplication] setStatusBarHidden:YES animated:YES];    
    [self.navigationController.view setNeedsLayout];
    

but that doesn't seem to work.

Any help appreciated. Thanks

like image 538
eddy Avatar asked Mar 06 '10 19:03

eddy


4 Answers

There are two ways that you can do what you are asking.

One is to manually move the navigation bar:

In viewWillAppear:

    [UIApplication sharedApplication].statusBarHidden = YES;
    self.view.frame = [UIScreen mainScreen].applicationFrame;
    CGRect frame = self.navigationController.navigationBar.frame;
    frame.origin.y = 0;
    self.navigationController.navigationBar.frame = frame;

In viewWillDisappear:

    [UIApplication sharedApplication].statusBarHidden = NO;
    CGRect frame = self.navigationController.navigationBar.frame;
    frame.origin.y = 20.0;
    self.navigationController.navigationBar.frame = frame;

Things will also be okay if you are willing to turn off the navigation bar as well, although I suspect that is not what you wanted:

    [UIApplication sharedApplication].statusBarHidden = YES;
    self.navigationController.navigationBarHidden = YES;
like image 139
Ron Avatar answered Sep 29 '22 09:09

Ron


You should try resizing the frame of your UIViewControllers's view after you have hidden the StatusBar. The applicationFrame updates it's origin.y and size.height during the setStatusBarHidden:animated: method.

CGRect rect = [UIScreen mainScreen].applicationFrame;
self.view.frame = rect;

[self.view setNeedsLayout];
like image 41
Ian Gordon Avatar answered Sep 29 '22 11:09

Ian Gordon


I found the solutions above didn't quite work when the view is in the middle of an animated presentation, so I deferred hiding the status bar as follows:

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

    // doesn't work immediately because modal view has to finish loading
    dispatch_async(dispatch_get_main_queue(), ^(){
        [[UIApplication sharedApplication] setStatusBarHidden:YES];
        self.view.frame = [UIScreen mainScreen].applicationFrame;
    });
}
like image 28
Code Roadie Avatar answered Sep 29 '22 10:09

Code Roadie


In your root view controller (where you want to show the status bar):

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

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

In the view controller you push on the stack (where you want to hide the status bar):

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

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

Edit:

I realize now you want to hide the status bar. Got them mixed up since you were showing/hiding the nav bar in the code you posted. My mistake. It's essentially the same code, anyway:

In your root view controller (where you want to show the status bar):

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

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

In the view controller you push on the stack (where you want to hide the status bar):

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

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

I just tested this with an existing project and it worked.

like image 20
Shaggy Frog Avatar answered Sep 29 '22 11:09

Shaggy Frog