Add a navigation bar to a view without a navigation controller

42,321

Solution 1

While there are several smart ways to answer your question. I just solved it programmatically and wrote the following code in my viewWillAppear (note - viewDidLoad is also okay, but not suggested) -

-(void) viewWillAppear:(BOOL)animated {

    UINavigationBar *myNav = [[UINavigationBar alloc]initWithFrame:CGRectMake(0, 0, 320, 50)];
    [UINavigationBar appearance].barTintColor = [UIColor lightGrayColor];
    [self.view addSubview:myNav];


    UIBarButtonItem *cancelItem = [[UIBarButtonItem alloc] initWithTitle:@"Cancel"
                                                                   style:UIBarButtonItemStyleBordered
                                                                  target:self
                                                                  action:nil];

    UIBarButtonItem *doneItem = [[UIBarButtonItem alloc] initWithTitle:@"Done"
                                                                 style:UIBarButtonItemStyleBordered
                                                                target:self action:nil];


    UINavigationItem *navigItem = [[UINavigationItem alloc] initWithTitle:@"Navigation Title"];
    navigItem.rightBarButtonItem = doneItem;
    navigItem.leftBarButtonItem = cancelItem;
    myNav.items = [NSArray arrayWithObjects: navigItem,nil];

    [UIBarButtonItem appearance].tintColor = [UIColor blueColor];
}

So, you have a white navigation bar with blue bar button items without a Navigation controller. Again, there are other ways to implement it in your case. Hope, this was helpful.

Output -

enter image description here

Update -

To add images -

UIImageView *myImage = [[UIImageView alloc] initWithFrame:CGRectMake(0,10,32,32)];
[myImage setImage:[UIImage imageNamed:@"image.png"]];
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:myImage];
[self.view addSubview:myImage];

Solution 2

Swift 4 Version

 let navigationBar = UINavigationBar(frame: CGRect(x: 0, y: 0, width: 320, height: 50))
    navigationBar.barTintColor = UIColor.lightGray
    view.addSubview(navigationBar)

    let cancelButton = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: nil)
    let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: nil)

    let navigationItem = UINavigationItem(title: "Title")
    navigationItem.leftBarButtonItem = cancelButton
    navigationItem.rightBarButtonItem = doneButton

    navigationBar.items = [navigationItem]

Solution 3

There is a way to use the NavigationItem in interface builder for this.

First add a NavigationItem to your ViewController in the interface builder, like you would with a NavigationController. Make sure to make the NavigationBar is visible by selecting something other than Inferred and None under simulated metrics.

Second, in viewDidLoad, just add the following lines:

- (void)viewDidLoad 
{
    [super viewDidLoad];

    UINavigationBar *bar = [[UINavigationBar alloc] initWithFrame: frame];
    bar.items = @[self.navigationItem];
    [self.view addSubview: bar];
}

As for frame, width will be the same as your ViewController and height will be either 44.0 or 64.0 depending if the status bar is visible or not.

CGFloat navigationBarHeight = 44.f + [UIApplication sharedApplication].statusBarFrame.size.height;
CGRect frame = CGRectMake(0, 0, self.view.frame.size.width, navigationBarHeight);

And if you wish to support different orientations use NSLayoutConstraints:

    CGFloat navigationBarHeight = 44.f + [UIApplication sharedApplication].statusBarFrame.size.height;
[self.view addConstraints: @[
    [NSLayoutConstraint constraintWithItem: self.view
                                 attribute: NSLayoutAttributeLeft
                                 relatedBy: NSLayoutRelationEqual
                                    toItem: bar
                                 attribute: NSLayoutAttributeLeft
                                multiplier: 1.0
                                  constant: 0.0],
    [NSLayoutConstraint constraintWithItem: self.view
                                 attribute: NSLayoutAttributeRight
                                 relatedBy: NSLayoutRelationEqual
                                    toItem: bar
                                 attribute: NSLayoutAttributeRight
                                multiplier: 1.0
                                  constant: 0.0],
    [NSLayoutConstraint constraintWithItem: self.view
                                 attribute: NSLayoutAttributeTop
                                 relatedBy: NSLayoutRelationEqual
                                    toItem: bar
                                 attribute: NSLayoutAttributeTop
                                multiplier: 1.0
                                  constant: 0.0],
    [NSLayoutConstraint constraintWithItem: bar
                                 attribute: NSLayoutAttributeHeight
                                 relatedBy: NSLayoutRelationEqual
                                    toItem: nil
                                 attribute: NSLayoutAttributeNotAnAttribute
                                multiplier: 1.0
                                  constant: navigationBarHeight],
                             ]];

Solution 4

be very careful about adding in "viewWillAppear", as this method can be called more times, (for example is a modal appears....) so use a lazy approach:

1) declare a var:

var myNav: UINavigationBar?

2) test if already set:

viewWillAppear:(BOOL)animated {
if self.myNav != nil{
     return
}
self.myNav = ....

3) be sure remove exiting controller, for example on didDisappear...

note.. is not correct to specify size.. if iOS rotates, it does not work fine..

Share:
42,321

Related videos on Youtube

user3381665
Author by

user3381665

Updated on August 25, 2020

Comments

  • user3381665
    user3381665 over 3 years

    I have a side menu that slides out to display a table view and from there I have segues that use the reveal view controller. The segue has to connect directly to the view controller; I can't use a navigation controller.

    How do I add a navigation bar with a bar button item without a navigation controller?

    the story board has the navigation item

    the app does not

  • user3381665
    user3381665 almost 10 years
    hello, thanks for this great solution but do you know how to have an image button where it says cancel rather than just text?
  • raurora
    raurora almost 10 years
    Updated my answer. Hey, you made me code a lot. I am sure, you can customize your code and make it functional.
  • user3381665
    user3381665 almost 10 years
    sorry about that man, I'm new to this from Android and I'm just making this one IOS app cause the rest of my team is leave.
  • raurora
    raurora almost 10 years
    I always heard that the transition is easier when you jump from either iOS or Android to another. Anyway, good luck!