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?
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 -
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];
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],
]];
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.rightBarButtonItem = cancelButton
navigationItem.leftBarButtonItem = doneButton
navigationBar.items = [navigationItem]
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...
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..