10
votes

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.

7
Note that this is an area where differences exist between iOS 5 and earlier versions. If you use the "canned" layout for the navigation controller it's fairly portable, but if you've customized it at all then things jump around quite a bit between the two versions. (I've never quite nailed down what makes the difference, but what you're showing is typical for iOS 4 code running on iOS 5.)Hot Licks
see this first answer of this question stackoverflow.com/questions/5850705/…CarmeloS

7 Answers

11
votes

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);
7
votes

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.

7
votes

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

1
votes

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);
0
votes

Since you're adding advancedVC as a subview of self.view, it is being added inside the frame of self.view which I'm guessing is already compensating for the status bar.

You can probably easily fix this by adding this line:

nav.view.frame = self.view.frame;

Just above this line:

self.view = nav.view;

-

Other Thoughts

I'm not privy to your entire setup, but self.view may not be needed at all. Simply make your advancedVC instance the rootViewController of the UIWindow instance contained in your App Delegate.

0
votes

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.

0
votes

The problem is that UINavigationController.view should be added to the top view. Just find the top one and it will be working great.