UINavigationController has extra status bar gap at top

13,226

Solution 1

The problem was resolved by fixing the way the navigation controller was inserted. Instead of inserting it into a view that had been put onto the tabbar controller, the navigaiton controller should have been put directly onto the navigation controller.

advancedSearchFormVC = [[AdvancedSearchFormVC alloc] initWithNibName:@"AdvancedSearchForm" bundle:nil];
UINavigationController *searchNavController = [[UINavigationController alloc] initWithRootViewController:advancedSearchFormVC];

This is just one controller that is on the tabbar controller, replacing the advancedSearchFormVC at the same time. Then this nav controller was added to the array of controllers that got put onto the tabbar controller.

Sorry for any trouble, but this was one of those problems I can look directly at and not see it. I should have seen this earlier, because I had another nav controller already on the tabbar controller, and it was set up the same way.

Thanks for your assistance.

Solution 2

The problem is indeed that the navigation controller always expects to leave room for the status bar, which is the 20 pixel gap. I searched around for a while before I found this solution which works:

//nav is assumed to be a subclass or instance of UINavigationController
nav.view.frame = CGRectOffset(nav.view.frame, 0.0, -20.0);
//you can then add the navigation's view as a subview to something else

I originally found an answer which did this offset to the navigationbar's view, but it didn't work. It works when you do it to the navigation controllers actual view.

I use this technique to add a navigation controller from another nib to an empty view of my main nib, so I can position it anywhere within the main screen as a subview. By using an empty view as a placeholder and positioning frame on my main nib, I create a separate nib and class to manage the navigation, which manages other nibs used to handle their screens. This way I can solve the classic "how do I add a banner, image, or custom views above my navigation controller" while having a navigation controller as a subview...in iOS 5 to be specific.

It's also worth mentioning that I use the app delegate to store and access all the other controllers, so they are retained by a persistant instance which I can access from any class. Create and synthesise some properties in the app delegate of all your controllers, and in viewDidLoad create instances. That way I can reference all the controllers used in my app later anywhere by adding:

//this shows how to store your navigation controllers in the app delegate
//assumes you've added 2 properties (UINavigationController*)"navController" and (UIViewController*)"rootController" in your app delegate
//...don't forget to add #import "AppDelegate.h" to the top of the file

AppDelegate *app = (AppDelegate*)[[UIApplication sharedApplication] delegate];
[app.navController pushViewController: app.rootController animated:YES];
//now apply the offset trick to remove the status gap
app.navController.view.frame = CGRectOffset(app.navController.view.frame, 0.0, -20.0);

Solution 3

I had the same problem before. The code I used to add UINavigationBar to UIViewController:

UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:self];
[self.view  addSubview:nc.view];

Solution:
Check the box "Wants Full Screen" with Attributes inspector of your UIViewController.

Solution 4

You can try to set the attribute Under Top Bars unchecked from Attributes section of UIViewController.

Solution 5

As we all know by now, the 20 pixel shift is to provide space for the Status bar on the top. But infact, the view controllers coordinate system is kept in place and only the navigation bar frame is shifted down by 20 pixels. This makes the navigation bar to actually overlap the top 20 pixels of the view.

Logging the navigation bars frame origin, it will show (0.0, 20.0)

So the solution is to simply reposition the navigation bar's origin to (0.0, 0.0) in ViewWillAppear.

self.navigationController.navigationBar.frame = CGRectMake(0.0, 0.0, self.navigationController.navigationBar.frame.size.width, self.navigationController.navigationBar.frame.size.height);
Share:
13,226
Jim
Author by

Jim

I am a Systems Engineer with many years of experience in electronic systems, including space and terrestrial communication systems, network systems, and radar systems, with a focus on signal processing and architecture. "Know your customer and his/her needs." My hobbies include photography, yachting, software development, writing, and foreign languages. If you don't know what to do with your spare time, go walk your dog. If you don't have a dog, walk someone else's dog. It's a better way for you to spend your time than what you are doing right now. If you think you don't have any spare time, then you probably don't have a dog. Recently distributed iOS app: LarkSpree Lite.

Updated on July 16, 2022

Comments

  • Jim
    Jim almost 2 years

    This looked simple enough when I set it up, but I can't explain why this gap is present between the status bar and the navigation bar. Also, the contained view looks like it may be properly aligned, and it's just the nav bar that is shifted down. The gap looks like the size of the status bar, so I expect that has something to do with it, but I don't know what.

    Nav Bar with extra space

    Here is the code for setting up the navigation controller:

    - (void)viewDidLoad
    {
        [super viewDidLoad];
    
        advancedVC = [[AdvancedSearchFormVC alloc] initWithNibName:@"AdvancedSearchForm" bundle:nil];
        UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:advancedVC];
        nav.navigationBar.tintColor = [UIColor defaultNavBarTint];
        nav.navigationBar.topItem.title = NSLocalizedString(@"SearchTitle", nil);
        UIBarButtonItem *searchButton = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"SearchButton", nil) style:UIBarButtonItemStylePlain target:self action:@selector(refreshPropertyList:)];          
        nav.navigationBar.topItem.rightBarButtonItem = searchButton;
    
        self.view = nav.view;
    }
    

    The rootViewController uses a view from a xib file, where I have simulated the status bar, the navigation bar, and the tab bar.

  • DoctorG
    DoctorG almost 12 years
    Jim -- I'm not following your solution exactly. Can you post code to show the actual fix please?