I want to set custom back bar button for all controllers in the app. I tried using this:
[[UIBarButtonItem appearance]
setBackButtonBackgroundImage:backButtonImage
forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
It sets the image. That's OK. But, what i really want to do is that, i just want a custom button for back bar button which does not contain any title etc. The code above works, but it adds automated titles and resizes the back bar button item. My need is to have a fixed frame, no-title back bar button item for all controllers in the app.
I've resolved it. Just make a category over UIViewController and import it in prefix.pch file. Then write a method: customViewWillAppear: and swizzle it with viewWillAppear method:
+(void)load{
Method viewWillAppear = class_getInstanceMethod(self, #selector(customViewWillAppear:));
Method customViewWillAppear = class_getInstanceMethod(self, #selector(viewWillAppear:));
method_exchangeImplementations(viewWillAppear, customViewWillAppear);
}
Add the above method to that category class. Then implement your customViewWillAppear method like this:
-(void)customViewWillAppear:(BOOL)animated{
[self customViewWillAppear:animated];
if([self.navigationController.viewControllers indexOfObject:self] != 0 && !self.navigationItem.hidesBackButton){
UIBarButtonItem *cancelBarButton = nil;
UIButton* cancelButton = [UIButton buttonWithType:UIButtonTypeCustom];
[cancelButton addTarget:self action:#selector(popViewControllerWithAnimation) forControlEvents:UIControlEventTouchUpInside];
[cancelButton setBackgroundImage:[UIImage imageNamed:#"yourImage.png"] forState:UIControlStateNormal];
[cancelButton sizeButtonToFit];
cancelBarButton = [[UIBarButtonItem alloc] initWithCustomView:cancelButton];
NSMutableArray * leftButtons = [NSMutableArray arrayWithObject:cancelBarButton];
[leftButtons addObjectsFromArray:self.navigationItem.leftBarButtonItems];
[self.navigationItem setLeftBarButtonItem:nil];
[self.navigationItem setLeftBarButtonItems:leftButtons];
}
[self.navigationItem setHidesBackButton:YES];
}
-(void)popViewControllerWithAnimation{
[self.navigationController popViewControllerAnimated:YES];
}
Now, for every controller in your code, you have a custom back button. This took me a lot of time to implement and figure out. Hope it'll help you guys all too.
EDIT:
Please use the following code to support iOS7> back swipe feature;
UIImage *image = [UIImage imageForName:#"some_image"];
navBar.backIndicatorImage = [image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
navBar.backIndicatorTransitionMaskImage = [image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
Create a base view controller and add the following code;
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"" style:UIBarButtonItemStylePlain target:nil action:nil];
}
I've had a similar problem before and I've searched everywhere for a solution.
The only one I've found, which works for your problem was to implement in EVERY view controller a UILeftBarButton which does the popping.
You can change the background image the way you're doing, but if you set the text to nil or empty text (""), you're button just won't show up.
You also can't change the View of the UIBackBarButton, only it's text (so no custom button).
What i did, was set the backbutton title label alpha to zero, using appearance proxy.
My code in ViewDidLoad:
// Set back button image
if ([[self.navigationController viewControllers] objectAtIndex:0] != self) {
UIButton *btnBack = [UIButton buttonWithType:UIButtonTypeCustom];
btnBack.frame = CGRectMake(0,0,38,30);
[btnBack setBackgroundImage:[UIImage imageNamed:#"NavigationBarBackButton"] forState:UIControlStateNormal];
[btnBack addTarget:self.navigationController action:#selector(popViewControllerAnimated:) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *leftBtn = [[UIBarButtonItem alloc] initWithCustomView:btnBack];
[self.navigationItem setLeftBarButtonItem:leftBtn];
}
You could write a category like this,
//
// UINavigationItem+BarAditions.h
//
// Created by Satheeshwaran on on 7/5/13.
//
#import <Foundation/Foundation.h>
#interface UINavigationItem (PersonaAddition)
- (void)setCustomBackButton;
#end
//
// UINavigationItem+BarAditions.m
//
// Created by Satheeshwaran on on 7/5/13.
//
#import "UINavigationItem+PersonaAddition.h"
#implementation UINavigationItem (PersonaAddition)
- (void)setCustomBackButton
{
//customize ur back button here.
UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom];
backButton.frame=CGRectMake(0, 0, 60, 30);
[backButton addTarget:target action:#selector(didPressLeftItem:) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *barItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
self.leftBarButtonItem = barItem;
}
and import this category in all ur files and call the setCustomBackButton in all ur classes. This works fine for me, even in iOS 7.
In ViewDidLoad of all ur classes.
- (void)viewDidLoad
{
[super viewDidLoad];
[self.navigationItem setCustomBackButton];
}
try this code:
UIButton *tempbtn = [[UIButton alloc] init];
[tempbtn setImage:[UIImage imageNamed:#"testbtn.png"] forState:UIControlStateNormal];
UIBarButtonItem *temp = [[UIBarButtonItem alloc] initWithCustomView:tempbtn];
self.navigationItem.rightBarButtonItem = temp;
Related
In my application there are many UIViewControllers with UINavigationControllers. There must be a "back" button and a "home" UIButton on the UINavigationBar. All of this works fine.
But some of my UIViewControllers have long names, and sometimes there is too small place left for it. I'm trying to replace the original label of the "back" button (it shows the title of the previous view) with a custom "Back", but whatever I tried it didn't work:
// Title didn't change
[self.navigationItem.backBarButtonItem setTitle:#"Back"];
// Action didn't set, no response from button ( button didn't do anything )
[self.navigationItem.leftBarButtonItem
setAction:self.navigationItem.backBarButtonItem.action];
And I need the "back" button to have a style like in this question: Draw custom Back button on iPhone Navigation Bar
Try the following. It will definitely work:
- (void)viewDidLoad {
[super viewDidLoad];
UIImage *buttonImage = [UIImage imageNamed:#"back.png"];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setImage:buttonImage forState:UIControlStateNormal];
button.frame = CGRectMake(0, 0, buttonImage.size.width, buttonImage.size.height);
[button addTarget:self action:#selector(back) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *customBarItem = [[UIBarButtonItem alloc] initWithCustomView:button];
self.navigationItem.leftBarButtonItem = customBarItem;
[customBarItem release];
}
- (void)back {
[self.navigationController popViewControllerAnimated:YES];
}
Make sure you have an button image with the size of a navigation bar back button in your resource folder with name back.png.
Feel free if any other assistance is required.
Target:
customizing all back button on UINavigationBar to an white icon
Steps:
1. in "didFinishLaunchingWithOptions" method of AppDelete:
UIImage *backBtnIcon = [UIImage imageNamed:#"navBackBtn"];
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"7.0")) {
[UINavigationBar appearance].tintColor = [UIColor whiteColor];
[UINavigationBar appearance].backIndicatorImage = backBtnIcon;
[UINavigationBar appearance].backIndicatorTransitionMaskImage = backBtnIcon;
}else{
UIImage *backButtonImage = [backBtnIcon resizableImageWithCapInsets:UIEdgeInsetsMake(0, backBtnIcon.size.width - 1, 0, 0)];
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:backButtonImage forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[[UIBarButtonItem appearance] setBackButtonTitlePositionAdjustment:UIOffsetMake(0, -backButtonImage.size.height*2) forBarMetrics:UIBarMetricsDefault];
}
2.in the "viewDidLoad" method of the common super ViewController class:
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"7.0")) {
UIBarButtonItem *backItem = [[UIBarButtonItem alloc] initWithTitle:#""
style:UIBarButtonItemStylePlain
target:nil
action:nil];
[self.navigationItem setBackBarButtonItem:backItem];
}else{
//do nothing
}
Try this
UIBarButtonItem *backBarBtnItem = [[UIBarButtonItem alloc] initWithTitle:#"Back" style:UIBarButtonItemStylePlain target:self action:#selector(popViewController)];
[self.navigationItem setBackBarButtonItem:backBarBtnItem];
- (void)popViewController
{
[self.navigationController popViewControllerAnimated:YES];
}
If you're doing this all over the place like I am, you're better off implementing Anil's solution as a category:
#interface UIViewController (CustomBackButton)
- (void) setCustomBackButton;
- (void) back;
#end
#implementation UIViewController (CustomBackButton)
- (void) setCustomBackButton
{
UIImage *buttonImage = [UIImage imageNamed:#"back.png"];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setImage:buttonImage forState:UIControlStateNormal];
button.frame = CGRectMake(0, 0, buttonImage.size.width, buttonImage.size.height);
[button addTarget:self action:#selector(back) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *customBarItem = [[UIBarButtonItem alloc] initWithCustomView:button];
self.navigationItem.leftBarButtonItem = customBarItem;
}
- (void) back
{
[self.navigationController popViewControllerAnimated:YES];
}
#end
More simply:
UIBarButtonItem *barBtnItem =
[[UIBarButtonItem alloc]initWithTitle:#"Indietro"
style:UIBarButtonItemStyleBordered
target:self
action:#selector(pop)];
[barBtnItem setTintColor:[UIColor whiteColor]];
self.navigationItem.leftBarButtonItem = barBtnItem;
Suppose you have two controllers - Controller1 and Controller2. Controller2 is pushed from Controller1. So before pushing the Controller2 on the navigationController from Controller1
Controller2 *controller2 = [[[Controller2 alloc] init]autorelease];
self.navigationItem.hidesBackButton = YES;
Now, in the viewDidLoad: method of Controller2, add the following snippet
UIBarButtonItem *backBarButtonItem =[[[UIBarButtonItem alloc]initWithTitle:#"Back" style:UIBarButtonItemStyleBordered target:self action:#selector(goBackToAllPets:)]autorelease];
self.navigationItem.leftBarButtonItem = backBarButtonItem;
and in the backButtonClicked method, you can perform the checks you want to.
I need to change the default title value of the back button in a navigationcontroller to something else.
I am trying this with the following code:
UIBarButtonItem *newBackButton = [[UIBarButtonItem alloc] initWithTitle: #"Terug" style: UIBarButtonItemStyleBordered target:nil action:nil];
self.navigationItem.backBarButtonItem = newBackButton;
[newBackButton release];
i also tried:
UIBarButtonItem *newBackButton = [[UIBarButtonItem alloc] initWithTitle: #"Terug" style: UIBarButtonItemStylePlain target:nil action:nil];
self.navigationItem.backBarButtonItem = newBackButton;
[newBackButton release];
I am using this code at the end of the viewDidLoad.
I am able to create a normal button (square) with the following code:
UIBarButtonItem *newBackButton = [[UIBarButtonItem alloc] initWithTitle: #"Terug" style: UIBarButtonItemStyleBordered target:nil action:nil];
self.navigationItem.leftBarButtonItem = newBackButton;
[newBackButton release];
The problem with this solution is that I need to create a seperate method that pop's the view controller. Another issue would be the shape of the button, I need an arrow shaped button.
do you have any idea?
If you want to have a custom back button you need to create new one and assign a new selector to it.
The backBarButtonItem is not editable, so you need to set the leftBarButtonItem.
This is how you can create a custom back button
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setTitle:NSLocalizedString(#"Back", nil) forState:UIControlStateNormal];
[button setBackgroundImage:[UIImage imageNamed:#"back.png"] forState:UIControlStateNormal];
[button addTarget:navigationController action:#selector(backAction:)forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithCustomView:button];
navigationController.navigationItem.leftBarButtonItem = backButton;
[backButton release];
And this is the selector to simulate the back button
- (IBAction)backAction:(id)sender
{
[self.navigationController popViewControllerAnimated:YES];
}
There is a simple solution
lets say you are moving from viewA to viewB
just before moving from viewA to viewB change the title of viewA
for example:
-(void)moveToViewB
{
// Add this line
self.title = #"Terug";
// and push the new view as normal
[self.navigationController pushViewController:viewB animated:NO];
}
Call this button from your 'viewDidLoad' method.
- (void)addCustomBackButton {
/* enter your image name and size here */
UIImage *backImage = [UIImage imageNamed:#"back_btn.png"];
CGRect buttonRect = CGRectMake(5.0f, 0.0f, 12.0f, 20.0f);
/* enter your image name and size here */
UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom];
[backButton addTarget:self action:#selector(backAction) forControlEvents:UIControlEventTouchUpInside]; // implemeent 'backAction' method in each VC
[backButton setFrame:buttonRect];
UIImageView *imageView = [[UIImageView alloc] initWithImage:backImage];
[imageView setFrame:buttonRect];
[backButton addSubview:imageView];
UIBarButtonItem *homeButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
self.navigationItem.leftBarButtonItem = homeButtonItem;
}
[Or, make it a class method of a 'Utitlity' class and call it as a class method in each viewContorller it is required.]
Also, don't forget to implement the 'backAction', something like this:
- (void)backAction
{
[self.navigationController popViewControllerAnimated:YES];
}
Happy coding!
i have to change the back button image. So for achieveing this i am using the following code:
//add the back button.
UIButton *home = [UIButton buttonWithType:UIButtonTypeCustom];
UIImage *homeImage = [UIImage imageNamed:#"back.png"];
[home setBackgroundImage:homeImage forState:UIControlStateNormal];
[home addTarget:self action:#selector(cancel:)
forControlEvents:UIControlEventTouchUpInside];
home.frame = CGRectMake(0, 0, 30, 30);
UIBarButtonItem *cancelButton = [[[UIBarButtonItem alloc]
initWithCustomView:home] autorelease];
self.navigationItem.backBarButtonItem = cancelButton;
also the method cancel defined in this view controller. I use the above code in viewDidLoad method. I am still not able to see the back button. No button shows up in the navigation bar.
I am writing this code in the viewcontroller that is loaded, and not in the previous view.
thank you in advance.
You have to set it as leftBarButtonItem.
self.leftBarButtonItem.backBarButtonItem = cancelButton;
In my iPhone application, I'm adding a toolbar on UINavigation controller as navigation bar do not take more then two bar buttons on it.
So far .. I have successfully added the UIToolBar with three BarButtonItems on it. However I am not able to display an image on BarButtonItems.
Can any one tell me .. how to add image on UIToolBar BarButtonItems? Where ToolBar is already added on nav controller.
Set a custom view for the UIBarButtonItem, something like this
UIBarButtonItem *barButton = [[UIBarButtonItem alloc] init];
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
UIImage *yourImage = [UIImage imageNamed:#"yourImage.png"];
[button setImage:yourImage forState:UIControlStateNormal];
[button addTarget:self action:#selector(yourButtonAction) forControlEvents:UIControlEventTouchUpInside];
[barButton setCustomView:button];
self.navigationItem.rightBarButtonItem = barButton;
[barButton release];
button = [[UIBarButtonItem alloc] initWithCustomView:[[UIImageView alloc] initWithImage:image]];
button.action = #selector(myaction);
button.target = self;
Try this.
I can create a button like this, and the action works fine:
UIBarButtonItem *myBtn = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:#"image.png"] style:UIBarButtonItemStyleBordered target:self action:#selector(myMethod:)];
However, when tapping the button on screen, no Down state highlight is displayed. I've tried everything. Can you not get a highlight on a UIBarButtonItem with a custom image?
Try something like this (setShowsTouchWhenHighlighted: is what you're looking for):
UIImage* image = [UIImage imageNamed:#"image.png"];
CGRect frame = CGRectMake(0, 0, image.size.width, image.size.height);
UIButton* button = [[UIButton alloc] initWithFrame:frame];
[button setBackgroundImage:image forState:UIControlStateNormal];
[button addTarget:self action:#selector(myMethod:) forControlEvents:UIControlEventTouchUpInside];
[button setShowsTouchWhenHighlighted:YES];
UIBarButtonItem* barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
[self.navigationItem setRightBarButtonItem:barButtonItem];
[barButtonItem release];
[button release];
Maybe something a little bit easier for most beginners:
Code for Button Creation
UIBarButtonItem *editButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"Edit" style:UIBarButtonItemStyleBordered target:self action:#selector(editCells:)];
self.navigationItem.rightBarButtonItem = editButtonItem;
[editButtonItem release];
Code for Action Handler
- (void)editCells:(id)sender {
UIBarButtonItem *buttonItem = (UIBarButtonItem *)sender;
if (self.tableView.editing == YES) {
self.tableView.editing = NO;
buttonItem.title = #"Edit";
buttonItem.style = UIBarButtonItemStyleBordered;
}
else {
self.tableView.editing = YES;
buttonItem.title = #"Done";
buttonItem.style = UIBarButtonItemStyleDone;
}
}
Explanation
Pretty straight forward. I create the button programatically and add it to the views navigation bar. Of course, this only works when using a NavigationController.
When the user clicks the button to start editing the related table view, the function checks the table editing state and changes the text of the button as well as the style.