How to add a button to UINavigationBar? - ios

How to add a button to UINavigationBar programmatically?

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;

The answers above are good, but I'd like to flesh them out with a few more tips:
If you want to modify the title of the back button (the arrow-y looking one at the left of the navigation bar) you MUST do it in the PREVIOUS view controller, not the one for which it will display. It's like saying "hey, if you ever push another view controller on top of this one, call the back button "Back" (or whatever) instead of the default."
If you want to hide the back button during a special state, such as while a UIPickerView is displayed, use self.navigationItem.hidesBackButton = YES; and remember to set it back when you leave the special state.
If you want to display one of the special symbolic buttons, use the form initWithBarButtonSystemItem:target:action with a value like UIBarButtonSystemItemAdd
Remember, the meaning of that symbol is up to you, but be careful of the Human Interface Guidelines. Using UIBarButtonSystemItemAdd to mean deleting an item will probably get your application rejected.

Adding custom button to navigation bar ( with image for buttonItem and specifying action method (void)openView{} and).
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(0, 0, 32, 32);
[button setImage:[UIImage imageNamed:#"settings_b.png"] forState:UIControlStateNormal];
[button addTarget:self action:#selector(openView) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *barButton=[[UIBarButtonItem alloc] init];
[barButton setCustomView:button];
self.navigationItem.rightBarButtonItem=barButton;
[button release];
[barButton release];

The example below will display a button with a title "Contact" on the navigation bar on the right. Its action calls a method named "contact" from the viewcontroller. Without this line the right button is not visible.
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"Contact"
style:UIBarButtonItemStylePlain target:self action:#selector(contact:)];;

In Swift 2, you would do:
let rightButton: UIBarButtonItem = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.Done, target: nil, action: nil)
self.navigationItem.rightBarButtonItem = rightButton
(Not a major change) In Swift 4/5, it will be:
let rightButton: UIBarButtonItem = UIBarButtonItem(title: "Done", style: UIBarButtonItem.Style.done, target: nil, action: nil)
self.navigationItem.rightBarButtonItem = rightButton

Why not use the following:
(from Draw custom Back button on iPhone Navigation Bar)
// Add left
UINavigationItem *previousItem = [[UINavigationItem alloc] initWithTitle:#"Back title"];
UINavigationItem *currentItem = [[UINavigationItem alloc] initWithTitle:#"Main Title"];
[self.navigationController.navigationBar setItems:[NSArray arrayWithObjects:previousItem, currentItem, nil] animated:YES];
// set the delegate to self
[self.navigationController.navigationBar setDelegate:self];

swift 3
let cancelBarButton = UIBarButtonItem(title: "Cancel", style: .done, target: self, action: #selector(cancelPressed(_:)))
cancelBarButton.setTitleTextAttributes( [NSFontAttributeName : UIFont.cancelBarButtonFont(),
NSForegroundColorAttributeName : UIColor.white], for: .normal)
self.navigationItem.leftBarButtonItem = cancelBarButton
func cancelPressed(_ sender: UIBarButtonItem ) {
self.dismiss(animated: true, completion: nil)
}

Related

Navigation bar item not showing complete

I can see just this (text should be "item" and it is showing "I...m")
When I try to add a navigation bar item using the storyboard. Anybody know why?
This is how I'm adding that button:
self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Item", style: .Plain, target: self, action: nil)
Put a UIButton as the customView of the UIBarButton to set a custom width of the UIBarButton.
// create the nav bar back button
UIButton *backButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 50, 24)];
[backButton setTitle:#"Item" forState:UIControlStateNormal];
[backButton addTarget:self action:#selector(backButtonAction) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *buttonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
self.navigationItem.leftBarButtonItem = buttonItem;

leftbarbuttonitem does not show up in the navigation bar

I've been developing an iOS app and have been having issues with using an image as the left bar button item in the navigation bar. I have attempted this in the following ways:
UIImage *backButtonImage = [UIImage imageNamed:#"backbuttonCB"];
CGRect buttonFrame = CGRectMake(0, 0, backButtonImage.size.width, backButtonImage.size.height);
UIButton *backButton = [[UIButton alloc] initWithFrame:buttonFrame];
[backButton setImage:backButtonImage forState:UIControlStateNormal];
UIBarButtonItem *backBarButtonItem= [[UIBarButtonItem alloc] initWithCustomView: backButton];
self.navigationItem.leftBarButtonItem = backBarButtonItem;
The bar button never seems to display while running the app.
I then proceeded to try this other method as follows.
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:#"backbuttonCB"] style:UIBarButtonItemStylePlain target:nil action:#selector(methodname)];
This method actually worked. However, the image displayed was tinted blue and did not look like it was meant to. Changing the tint colour of this image did not help.
Any idea how I can solve this problem?
EDIT: More information, if it helps.
This is the first view in the navigation stack. The navigation stack is displayed modally i.e. there is a previous view controller and there is a modal segue between the previous view controller and the navigation controller. This is the first view in the navigation stack.
EDIT: THE PROBLEM IS FIXED.
I think it was a bug in xcode because when I restarted xcode and tested it with an actual device instead of the emulator, it worked fine. However, still doesn't seem to work on an emulator.
Try setting your leftBarButtonItem this way. While presenting modally it doesn't shows up.
self.navigationController?.navigationBar.topItem.leftBarButtonItem =
Calling myButton.sizeToFit() before assigning to leftBarButtonItem helped me.
let cancelButton = UIButton()
cancelButton.backgroundColor = .red
cancelButton.setTitle("Common/Cancel".localized, for: .normal)
cancelButton.sizeToFit() //!!!
let cancelBarButton = UIBarButtonItem(customView: cancelButton)
navigationItem.leftBarButtonItem = cancelBarButton
Try to use this code,
self.navigationItem.hidesBackButton=YES;
UIImage *buttonImage = [UIImage imageNamed:#"Back"];
UIButton *aButton = [UIButton buttonWithType:UIButtonTypeCustom];
[aButton setImage:buttonImage forState:UIControlStateNormal];
aButton.frame = CGRectMake(0.0,0.0,buttonImage.size.width,buttonImage.size.height);
[aButton addTarget:self action:#selector(backBtnTapped) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithCustomView:aButton];
self.navigationItem.leftBarButtonItem = backButton;
I had the same problem. To see the button, I had to change the tint color, here's the code in Swift:
self.navigationItem.leftBarButtonItem = UIBarButtonItem.init(image:UIImage.init(named: "btn_back_default")!, style:UIBarButtonItemStyle.Plain, target: self, action: Selector("back"))
self.navigationItem.leftBarButtonItem?.tintColor = UIColor.whiteColor()
Updated for Swift 5:
let image = UIImage(named: "iconClose")
let button = UIBarButtonItem(image: image, style: .plain, target: self, action: #selector(self.cancel))
navigationItem.leftBarButtonItem = button
For me the problem on iOS 13 was due to the use of the native Apple SF Symbols as the image of the UIBarButtonItem.
My advice would be to use add your image to the assets or if you prefer using SF Symbols use the "#available" selector to used them in versions > iOS 14.0, see:
var img: UIImage
var backButton: UIBarButtonItem
if #available(iOS 14.0, *) {
img = UIImage(systemName: "chevron.backward")!
backButton = UIBarButtonItem(image: img, style: .plain, target: self, action: #selector(foo))
} else {
// add your image to the project's assets first and make sure that the name is the same
img = UIImage(named: "my-custom-image")!
backButton = UIBarButtonItem(image: img, style: .plain, target: self, action: #selector(foo))
}
self.navigationItem.leftBarButtonItem = backButton
Replace your code to initialize the button as a customType like this:
UIImage *backButtonImage = [UIImage imageNamed:#"backButtonCB"];
CGRect buttonFrame = CGRectMake(0, 0, backButtonImage.size.width, backButtonImage.size.height);
UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom];
[backButton setFrame:buttonFrame];
[backButton setImage:backButtonImage forState:UIControlStateNormal];
UIBarButtonItem *backBarButtonItem= [[UIBarButtonItem alloc] initWithCustomView: backButton];
self.navigationItem.leftBarButtonItem = backBarButtonItem;
Hope it helps....:)
Add a Navigation Item to the Views storyboard and create an outlet for it in the ViewController. Then, use your outlet instead of self.navigationController?.navigationItem to reference leftBarButtonItem.

ios7 navigation bar : 3 strange dots appearing when back animation with custom button

I would like to use the back navigation animation using
[self.navigationController popViewControllerAnimated:YES]
with a custom button added to the navigation bar.
As I don't want the back button to be seen, i've hidden it with self.navigationItem.hidesBackButton = YES;
But during the back animation, on ios7 (not ios6) 3 dots can be seen sliding in the navigation bar.
They are not appearing with self.navigationItem.hidesBackButton = NO; but of course the button can be seen.
Does anyone has any idea to make them not appearing ?
If you set
self.navigationItem.hidesBackButton = YES
iOS will sometimes generate three dots inside its generic back button.
I solved the problem by setting the text on the generic back button to be empty and then I created my custom button. This is how I set the empty text:
UIBarButtonItem *backButton2 = [[UIBarButtonItem alloc] initWithTitle:#"" style:UIBarButtonItemStylePlain target:nil action:nil];
self.navigationItem.backBarButtonItem = backButton2;
And then I created my custom UIButton and placed it where I wanted it like this:
UIButton *backButton = [[UIButton alloc] initWithFrame:CGRectMake(5, 70/2-22, 44, 44)];
[backButton setImage:[[UIImage imageNamed:#"back_button.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] forState:UIControlStateNormal];
backButton.tintColor = tintColor;
backButton.imageEdgeInsets = UIEdgeInsetsMake(-2, -15, 0, 0);
[backButton addTarget:self action:#selector(popCurrentViewController) forControlEvents:UIControlEventTouchUpInside];
No need to hide the backButton, you can just add custom back button, it will hide the default button.
- (void) viewDidLoad
{
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:#"Back" style:UIBarButtonItemStyleBordered target:self action:#selector(handleBack:)];
self.navigationItem.leftBarButtonItem = backButton;
}
- (void) handleBack:(id)sender
{
[self.navigationController popViewControllerAnimated:YES];
}
Just add these following lines in viewWillAppear method:
Swift:
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .Plain, target: nil, action: nil)
self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: "", style: .Plain, target: nil, action: nil)
Objective C:
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"" style:UIBarButtonItemStylePlain target:nil action:nil];
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"" style:UIBarButtonItemStylePlain target:nil action:nil];
That's all
navigationItem.backBarButtonItem = nil
Simpler swift version :
let emptyBackButton = UIBarButtonItem(title: "", style: .Plain, target: nil, action: nil)
navigationItem.hidesBackButton = true
navigationItem.backBarButtonItem = emptyBackButton
You don't need to write any code just follow 4 simple step and you done it.
Select your Main.storyboard
Select Navigation Bar in Navigation Controller
Select Attributes Inspector
Clear Tint color

Create a custom left back button on UINavigationBar WITH the standard arrow on the left

When I create a custom back button, I use the following code:
UIBarButtonItem *leftButton = [[UIBarButtonItem alloc]initWithTitle:#"Yeah" style:UIBarButtonItemStyleBordered target:self action:#selector(backButtonPressed:)];
self.navigationItem.leftBarButtonItem = leftButton;
This works fine, and I obtain this result:
I would have the same result, but with an arrow on the left, like this (when it's a standard back button, not a custom one):
How can I simply add this arrow ?
Finally, here's the snippet I use to define the back button's title with the standard left arrow in the current view, not in the parent view :
- (void)viewDidLoad {
[super viewDidLoad];
[self setTitle:#"Current View"];
// Get the previous view controller
UIViewController *previousVC = [self.navigationController.viewControllers objectAtIndex:self.navigationController.viewControllers.count - 2];
// Create a UIBarButtonItem
UIBarButtonItem *barButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"FooBar" style:UIBarButtonItemStyleBordered target:self action:#selector(yourSelector)];
// Associate the barButtonItem to the previous view
[previousVC.navigationItem setBackBarButtonItem:barButtonItem];
}
Here's the result :
Note : However, since it's not possible to add an action on a backBarButtonItem, you can refer to this great post if you want it to.
Updated for Swift
// Prev - no chevron...
//navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Back !", style: .plain, target: self, action: #selector(backPressed))
// adds the chevron
let vc = navigationController?.viewControllers.first
let button = UIBarButtonItem(title: "Go Back", style: .plain, target: self, action: #selector(backPressed))
vc?.navigationItem.backBarButtonItem = button
The easiest thing to do would be to set the title, in the parent controller (i.e. the one you want to nav back to). If you don't want this to be the same as the actual title displayed in that VC's view, you can change the title in viewWillDisappear to what you want on the next VC's back button, and then change it back to what you want in the parent in viewWillAppear.
If you are using storyboards, you can also set the back title directly in IB.
Finally, in order to create a custom back button, you can do something like:
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc]initWithTitle:#"Details" style:UIBarButtonItemStyleBordered target:nil action:nil];
...just be sure to do this in the presenting (or parent) view controller, not the view controller being loaded (the presented controller).
UIButton * backButton = [UIButton buttonWithType:UIButtonTypeCustom];
[backButton addTarget:self action:#selector(popViewController) forControlEvents:UIControlEventTouchUpInside];
[backButton setFrame:FRAME_DEFINE
[backButton setContentHorizontalAlignment:UIControlContentHorizontalAlignmentLeft];
[backButton setExclusiveTouch:YES];
[backButton setImage:[UIImage imageNamed:BACK_BUTTON_DEFAULT_ICON] forState:UIControlStateNormal];
[backButton setTitle:#"BACK" forState:UIControlStateNormal];
[backButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
UIBarButtonItem *backMenuBarButton = [[UIBarButtonItem alloc] initWithCustomView:backButton];
self.navigationItem.leftBarButtonItem = backMenuBarButton;
well you need to go with a background image and with title and
// Creates a back button instead of default behaviour (displaying title of previous screen)
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:#"back_arrow.png"]
style:UIBarButtonItemStyleBordered
target:self
action:#selector(backAction)];
tipsDetailViewController.navigationItem.leftBarButtonItem = backButton;
[backButton release];
I use code like:
UIBarButtonItem *leftBar = [[UIBarButtonItem alloc] init];
leftBar.title = #"Back";//Details
self.navigationController.navigationBar.topItem.backBarButtonItem = leftBar;
For Swift, using Erzekiel's answer as the basis for this, you can simplify it to -
extension UIViewController {
func setBackButtonTitle(to title: String) {
let barButtonItem = UIBarButtonItem(title: title, style: .plain, target: self, action: nil)
self.navigationItem.backBarButtonItem = barButtonItem
}
}
This should be called from the parent viewController, eg in viewWillDisappear -
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
self.setBackButtonTitle(to: "Back"))
}

programmatically adding button to UIToolbar

I am programmatically creating a UIToolbar with this code:
pickerTB = [[UIToolbar alloc]initWithFrame:CGRectMake(0, 0, 320, 44)];
[self.view addSubview:pickerTB];
How do i add one single button to it? It needs to say "Done" and the button must be able to call a method later on.
Try this, If you want to add DONE button on right side of uitoolbar then add flexible button before done button
UIBarButtonItem *flexButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil];
UIBarButtonItem *doneButton =[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(doneButton)];
NSArray *itemsArray = [NSArray arrayWithObjects:flexButton, doneButton, nil];
[toolbar setItems:itemsArray];
-(void)doneButton
{
}
// change toolbar style
[toolbar setBarStyle:UIBarStyleBlackTranslucent];
//change bar button color
[doneButton setTintColor:[UIColor blackColor]];
pickerTB.items = [NSArray arrayWithObjects:[[UIBarButtonItem alloc]initWithTitle:#"Done" style:UIBarButtonItemStyleDone target:self action:#selector(done:)],nil];
This code will really helpful to add button to the UIToolbar present in keyboard or pickerview.
For example:
If you want "Done" button to be inserted in the toolbar of the pickerview. you just have to follow simple steps as follows.
Step 1:
Have to include this code inside "viewDidLoad" to create "Done" button in UIToolbar. "textBoxText" is the name of the Text field.
// create done button in toolbar.
doneToolbar = UIToolbar(frame: CGRectMake(0, 0, self.view.frame.size.width, 50))
doneToolbar.barStyle = UIBarStyle.Default
doneToolbar.items = [UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.Plain, target: self, action: #selector(FirstViewController.PickerDoneButtonTapped))]
doneToolbar.sizeToFit()
textBoxText.inputAccessoryView = doneToolbar
Step 2:
Code the function of "Done" button that has included in the UIToolbar. I have given that if "Done" button is tapped the PickerView have to disable.
func PickerDoneButtonTapped()
{
textBoxText.resignFirstResponder()
}
Step 3:
Have to call the function in "viewDidload"
self.PickerDoneButtonTapped()
Output:

Resources