How to Add a Button to Uinavigationbar

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



Leave a reply



Submit