How to add a button to UINavigationBar?
Sample code to set the rightbutton
on a NavigationBar
.
UIBarButtonItem *rightButton = [[UIBarButtonItem alloc] initWithTitle:@"Done"
style:UIBarButtonItemStyleDone target:nil action:nil];
UINavigationItem *item = [[UINavigationItem alloc] initWithTitle:@"Title"];
item.rightBarButtonItem = rightButton;
item.hidesBackButton = YES;
[bar pushNavigationItem:item animated:NO];
But normally you would have a NavigationController
, enabling you to write:
UIBarButtonItem *rightButton = [[UIBarButtonItem alloc] initWithTitle:@"Done"
style:UIBarButtonItemStyleDone target:nil action:nil];
self.navigationItem.rightBarButtonItem = rightButton;
Swift 3.0 Adding a Right Button to Navigation Bar
You say you added a UINavigationBar
to your view controller via storyboard, but looking at the code you provided there is no outlet connection to your navigation bar in IB.
In order to access self.navigationItem
your view controller must be embedded in a UINavigationController
or be part of a hierarchy which is. Unless you have a need for a custom navigation bar on an individual view controller, I suggest removing that from Interface Builder, then making sure either the view controller in question is embedded in a UINavigationController
or it is being pushed onto the navigation stack from another controller which is embedded in a navigation controller and then you should see your UIBarButtonItem
.
UIBarButtonItem in navigation bar programmatically?
Custom button image without setting button frame:
You can use init(image: UIImage?, style: UIBarButtonItemStyle, target: Any?, action: Selector?)
to initializes a new item using the specified image and other properties.
let button1 = UIBarButtonItem(image: UIImage(named: "imagename"), style: .plain, target: self, action: Selector("action")) // action:#selector(Class.MethodName) for swift 3
self.navigationItem.rightBarButtonItem = button1
Check this Apple Doc. reference
UIBarButtonItem with custom button image using button frame
FOR Swift 3.0
let btn1 = UIButton(type: .custom)
btn1.setImage(UIImage(named: "imagename"), for: .normal)
btn1.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
btn1.addTarget(self, action: #selector(Class.Methodname), for: .touchUpInside)
let item1 = UIBarButtonItem(customView: btn1)
let btn2 = UIButton(type: .custom)
btn2.setImage(UIImage(named: "imagename"), for: .normal)
btn2.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
btn2.addTarget(self, action: #selector(Class.MethodName), for: .touchUpInside)
let item2 = UIBarButtonItem(customView: btn2)
self.navigationItem.setRightBarButtonItems([item1,item2], animated: true)
FOR Swift 2.0
and older
let btnName = UIButton()
btnName.setImage(UIImage(named: "imagename"), forState: .Normal)
btnName.frame = CGRectMake(0, 0, 30, 30)
btnName.addTarget(self, action: Selector("action"), forControlEvents: .TouchUpInside)
//.... Set Right/Left Bar Button item
let rightBarButton = UIBarButtonItem()
rightBarButton.customView = btnName
self.navigationItem.rightBarButtonItem = rightBarButton
Or simply use init(customView:) like
let rightBarButton = UIBarButtonItem(customView: btnName)
self.navigationItem.rightBarButtonItem = rightBarButton
For System UIBarButtonItem
let camera = UIBarButtonItem(barButtonSystemItem: .Camera, target: self, action: Selector("btnOpenCamera"))
self.navigationItem.rightBarButtonItem = camera
For set more then 1 items use rightBarButtonItems
or for left side leftBarButtonItems
let btn1 = UIButton()
btn1.setImage(UIImage(named: "img1"), forState: .Normal)
btn1.frame = CGRectMake(0, 0, 30, 30)
btn1.addTarget(self, action: Selector("action1:"), forControlEvents: .TouchUpInside)
let item1 = UIBarButtonItem()
item1.customView = btn1
let btn2 = UIButton()
btn2.setImage(UIImage(named: "img2"), forState: .Normal)
btn2.frame = CGRectMake(0, 0, 30, 30)
btn2.addTarget(self, action: Selector("action2:"), forControlEvents: .TouchUpInside)
let item2 = UIBarButtonItem()
item2.customView = btn2
self.navigationItem.rightBarButtonItems = [item1,item2]
Using setLeftBarButtonItem
or setRightBarButtonItem
let btn1 = UIButton()
btn1.setImage(UIImage(named: "img1"), forState: .Normal)
btn1.frame = CGRectMake(0, 0, 30, 30)
btn1.addTarget(self, action: Selector("action1:"), forControlEvents: .TouchUpInside)
self.navigationItem.setLeftBarButtonItem(UIBarButtonItem(customView: btn1), animated: true);
For swift >= 2.2 action should be
#selector(Class.MethodName)
... for e.g.btnName.addTarget(self, action: #selector(Class.MethodName), forControlEvents: .TouchUpInside)
Add buttons to subclass of UINavigationBar
This is tough to do because UIViewController comes with its own UINavigationItems, see the docs here in the header file for UIViewController:
NS_CLASS_AVAILABLE_IOS(2_0) @interface UIViewController : UIResponder <NSCoding, UIAppearanceContainer, UITraitEnvironment, UIContentContainer> {
@package
UIView *_view;
UITabBarItem *_tabBarItem;
UINavigationItem *_navigationItem;
You'd have to override this function of UIViewController which is possible but requires you to subclass UIViewController and then force all your view controllers in app to be subclasses of your subclassed view controller, so that's the hard way, I'd show the code for it, but it's sort of intense and a lot of code, but this is how I do it. Anyway, the better option is to do this in your ViewDidLoad of your UIViewController:
- (void)viewDidLoad
{
[super viewDidLoad];
UIBarButtonItem * tester = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"reveal-icon"] style:UIBarButtonItemStylePlain target:self action:@selector(menuItemPressed:)];
[[self navigationItem] setRightBarButtonItem:tester];
}
You can still subclass the UINavigationBar, but don't use it as a subclass to try to override the barbuttonitems already hooked to a UIViewController that comes as default from UIKit, if you want to get nuts about this, then here's the start of how you subclass a UIViewController, it's a lot of code:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self == nil)
return nil;
if (self) {
_showsNotifications = false;
_showsAddFriends = false;
}
_notificationsBarButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage resizeImage:[UIImage imageNamed:@"YOUR IMAGE NAME"] height:27] style:UIBarButtonItemStylePlain target:nil action:nil];
_addFriendsBarButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"YOUR IMAGE NAME"] style:UIBarButtonItemStylePlain target:self action:@selector(addFriendsPressed)];
}
You see, you add to your custom view controller Bool properties that change the innards of the UINavigationItems in UIViewController. Using this method then requires you to call and set these bool values in your INIT of your viewcontrollers that are subclasses of this custom viewcontroller, do this like so:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
[self setShowsAddFriends:false];
[self setShowsNotifications:false];
}
return self;
}
Then in the subclassed UIViewController, make the bool switches able to actually switch.
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if (_showsNotifications) {
[[self navigationItem] setRightBarButtonItem:_notificationsBarButtonItem];
}
if (_showsAddFriends) {
[[self navigationItem] setRightBarButtonItem:_addFriendsBarButtonItem];
}
}
Done and done, complicated? Sort of, but this is how you template projects with as many custom Navigation item buttons as you want, the full code is about 1k lines of code, but this is the guts of it, subclass UIViewController, set bool properties in header, set these bool properties in your subclass so that the UIViewControllers that use this subclass as their parent class can call to these bool setter properties in "init", then you will be able to switch and choose whichever navigation items you like. In addition, to make sure that your view controllers maintain the items you set to them, make sure you also declare these item settings in your viewWillAppear in the view controllers that use your custom subclass of UIViewController as your parent view. Good luck, and have a good day.
In fact, I'll just show you the code, why? Because I'm bored and have too much to do with two app launches next week. So, here's the files you will need to look at, and keep in mind these are very much simplified:
CCUSTViewController.m
//******CCUSTViewController.m****
//this is the implementation file for the subclass of UIViewController
#import "CCUSTViewController.h"
#import "CCUSTFriendsViewController.h"
#import "CCUSTActivitiesViewController.h"
@interface CCUSTViewController ()
@end
@implementation CCUSTViewController
{
UIBarButtonItem * _notificationsBarButtonItem;
UIBarButtonItem * _addFriendsBarButtonItem;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self == nil)
return nil;
if (self) {
_showsNotifications = false;
_showsAddFriends = false;
}
_notificationsBarButtonItem = [[UIBarButtonItem alloc] initWithImage::[UIImage imageNamed:@"your imate"] style:UIBarButtonItemStylePlain target:self action:@selector(showNotificationsPressed)];
_addFriendsBarButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"your imate"] style:UIBarButtonItemStylePlain target:self action:@selector(addFriendsPressed)];
return self;
}
- (void)showNotificationsPressed
{
CCUSTActivitiesViewController * tobePushed = [CCUSTActivitiesViewController new];
[self navigationController] pushViewController:tobePushed animated:true];
}
- (void)addFriendsPressed
{
CCUSTFriendsViewController * tobePushed = [CCUSTFriendsViewController new];
[self navigationController] pushViewController:tobePushed animated:true];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if (_showsNotifications) {
[[self navigationItem] setRightBarButtonItem:_notificationsBarButtonItem];
}
if (_showsAddFriends) {
[[self navigationItem] setRightBarButtonItem:_addFriendsBarButtonItem];
}
}
@end
CCUSTViewController.h
#import <UIKit/UIKit.h>
@interface CCUSTViewController : UIViewController
@property (nonatomic) BOOL showsNotifications;
@property (nonatomic) BOOL showsAddFriends;
@end
Then, here's an example of a subclasses View controller using your new navigation bar items switcher:
CCCUSTHomeViewController.h
#import "CCUSTViewController.h"
@interface CCCUSTHomeViewController : CCUSTViewController
@end
CCCUSTHomeViewController.m
// CCCUSTHomeViewController.m
#import "CCCUSTHomeViewController.h"
#import "CCCUSTHomeView.h"
@interface CCCUSTHomeViewController ()
@end
@implementation CCCUSTHomeViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
[self setShowsAddFriends:TRUE];
[self setShowsNotifications:TRUE];
}
return self;
}
-(void)loadView
{
[self setView:[CCCUSTHomeView new]];
}
-(CCCUSTHomeView*)contentView
{
return (id)[self view];
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self setTitle:@"HOME"];
}
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self setShowsAddFriends:TRUE];
[self setShowsNotifications:TRUE];
}
@end
Oh yes, and you need to add the same code from the init to the ViewWillAppear because when you pop the pushed view controller on the stack, you will need to intercept this even in your CCCUSTHomeViewController so that the UINavigationItems reappear as they are supposed to given the viewcontroller that is on the top the stack. You can also subclass everything from UICollectionViewController and UITableViewController doing the same method, this means that using this structure as a template, you can have an empty project in Xcode with all these subclasses added to it and then you will have more control over all your view controllers. There's much much much much more that you can do implementing this method, but some things, I must keep secret, but suffice it to say, a lot of big apps use this same technique and the additional advanced techniques that you won't see out in the wild. The neat thing is that you don't have to delegate, and you don't have manipulate much of anything. Best of luck, and have a good day.
GISTS because I care:
https://gist.github.com/anonymous/993e457561001cf8e77b
https://gist.github.com/anonymous/bc6095575038c36de77b
https://gist.github.com/anonymous/78b450d2a805781ab8a4
https://gist.github.com/anonymous/a0757179c17dd7078bb2
add button navigationbar center
The titleView
is nil
by default so your code doesn't do anything.
Change the code to:
self.navigationItem.titleView = button;
This sets your button as the titleView
.
Add button to navigationbar programmatically
Inside my UIViewController
derived class, I am using the following inside viewDidLoad
:
UIBarButtonItem *flipButton = [[UIBarButtonItem alloc]
initWithTitle:@"Flip"
style:UIBarButtonItemStyleBordered
target:self
action:@selector(flipView:)];
self.navigationItem.rightBarButtonItem = flipButton;
[flipButton release];
This adds a button to the right hand side with the title Flip, which calls the method:
-(IBAction)flipView
This looks very much like you #3, but it is working within my code.
How to add a right button to a UINavigationController?
Try doing it in viewDidLoad. Generally you should defer anything you can until that point anyway, when a UIViewController is inited it still might be quite a while before it displays, no point in doing work early and tying up memory.
- (void)viewDidLoad {
[super viewDidLoad];
UIBarButtonItem *anotherButton = [[UIBarButtonItem alloc] initWithTitle:@"Show" style:UIBarButtonItemStylePlain target:self action:@selector(refreshPropertyList:)];
self.navigationItem.rightBarButtonItem = anotherButton;
// exclude the following in ARC projects...
[anotherButton release];
}
As to why it isn't working currently, I can't say with 100% certainty without seeing more code, but a lot of stuff happens between init and the view loading, and you may be doing something that causes the navigationItem to reset in between.
How to add right button in the navigation bar?
The Swift version of Vahan Babayan's answer, as you seem to use this language, is:
let rightButtonItem = UIBarButtonItem.init(
title: "Title",
style: .Done,
target: self,
action: "rightButtonAction:"
)
self.navigationItem.rightBarButtonItem = rightButtonItem
The following method will be called on self:
func rightButtonAction(sender: UIBarButtonItem)
Note that all this can be set graphically using a Storyboard, by dragging a Bar Button Item to your Navigation Item and right-clicking to set a target-action.
A small update since Swift 3 and 4 are out: the compiler can now check selector names, preventing typos when setting up target-action programatically. So one should really use:
let rightButtonItem = UIBarButtonItem.init(
title: "Title",
style: .Done,
target: self,
action: #selector(rightButtonAction(sender:))
)
Related Topics
This Class Is Not Key Value Coding-Compliant for the Key Xxxxxx
Is There Any Way of Asking an iOS View Which of Its Children Has First Responder Status
Uirefreshcontrol on Uicollectionview Only Works If the Collection Fills the Height of the Container
Why Is My iOS App Not Showing Up in Other Apps' "Open In" Dialog
How to Change the Color of an Uiimage
How to Generate a Barcode from a String in Swift
Swift Protocol Get Only Settable
Uitableviewrowaction Image for Title
Cordova Run with iOS Error .. Error Code 65 for Command: Xcodebuild with Args:
What Is Most Common and Correct Practice to Get a Cgfloat from an Nsnumber
How to Scale a Uibutton's Imageview
Dismissing Uialertviews When Entering Background State
Google Maps iOS Sdk, Getting Directions Between 2 Locations
How to Display the Standard Checkmark on a Uicollectionviewcell
iOS 13 Uibarbuttonitem Not Clickable and Overlapping Uinavigationbars When Using Uisearchcontroller