Can't change the background for UIBarButtonItem - ios

I need to change the default (which was already declared in my AppDelegate) background for UIBarButtonItem in one ViewController.
So, In my AppDelegate I have:
UIImage *navBarItemBackground = [UIImage imageNamed:#"navbar_button_green"];
[[UIBarButtonItem appearance] setBackgroundImage:navBarItemBackground
forState:UIControlStateNormal
style:UIBarButtonItemStyleBordered
barMetrics:UIBarMetricsDefault];
And when I need to restore the default background for the button - I implement in my viewController:
self.navigationItem.rightBarButtonItem = nil;
UIBarButtonItem *rightBarItem = [[UIBarButtonItem alloc] initWithTitle:#"Сохранить" style:UIBarButtonItemStyleBordered target:self action:#selector(clickOnSend:)];
[rightBarItem setBackgroundImage:[UIImage imageNamed:#""] forState:UIControlStateNormal style:UIBarButtonItemStyleBordered barMetrics:UIBarMetricsDefault];
self.navigationItem.rightBarButtonItem = rightBarItem;
But I think that it's not correct to set the empty file as the image. Is there more simple way to implement this behaviour? Thanks!

If you want to change only one or several UIViewController's UIBarButtonItems backgroundImage, you'd better change in the specific UIViewControllers as the latter case you use. while [[UIBarButtonItem appearance] setBackgroundImage:forState:style:barMetrics:]; will change all the UIBarButtonItems background image, which maybe not the better one.

You should change your code to this:
UIBarButtonItem * rightBarItem = [[UIBarButtonItem alloc]
initWithTitle: #"Сохранить"
style: UIBarButtonItemStyleBordered
target: nil action: nil];
UIImage *navBarItemBackground = [[UIImage imageNamed:#"navbar_button_green"]resizableImageWithCapInsets:UIEdgeInsetsMake(0, 13, 0, 6)];
[[UIBarButtonItem appearance] setBackgroundImage:navBarItemBackground
forState:UIControlStateNormal
barMetrics:UIBarMetricsDefault];
[self.navigationItem setBackBarButtonItem: rightBarItem];

Related

Can't change the background for UIBarButtonItem in a separate View Controller

in my appDelegate:
UIImage *navBarArrowItemBackground = [UIImage imageNamed:#"tabbar_button_back"];
[UIBarButtonItem appearance] setBackButtonBackgroundImage:navBarArrowItemBackground
forState:UIControlStateNormal
barMetrics:UIBarMetricsDefault];
and in separate view controller:
UIBarButtonItem* backButton = [[UIBarButtonItem alloc] initWithTitle:#"Back" style:UIBarButtonItemStylePlain target:self
action:nil];
[backButton setBackgroundImage:[UIImage imageNamed:#"tabbar_button_back_gray"] forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[self.navigationItem setBackBarButtonItem:backButton];
So on the child view controllers the title of the back button is changed but the background is taken from the appearance in appDelegate. I need a custom background for one view controller. How can I solve this?
edit#1:
now appDelegate looks like this:
UIImage *navBarArrowItemBackground = [UIImage imageNamed:#"tabbar_button_back"];
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:navBarArrowItemBackground
forState:UIControlStateNormal
barMetrics:UIBarMetricsDefault];
[[UIBarButtonItem appearanceWhenContainedIn:[SettingsListViewController class], nil] setBackButtonBackgroundImage: [UIImage imageNamed:#"tabbar_button_back_gray"] forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
You can achieve this by adding constraint to the appearence as follows:
[UIBarButtonItem appearanceWhenContainedIn:[YourOtherVC class], nil] setBackButtonBackgroundImage:navBarArrowItemBackground
forState:UIControlStateNormal
barMetrics:UIBarMetricsDefault];
Your code should be look like as follows:
UIImage *navBarArrowItemBackground = [UIImage imageNamed:#"tabbar_button_back"];
[[UIBarButtonItem appearanceWhenContainedIn:[SettingsListViewController class], nil] setBackButtonBackgroundImage: [UIImage imageNamed:#"tabbar_button_back_gray"] forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];

How do i remove text from back button on navbar within Xcode?

I set an arrow custom image to navigation bar by adding the following code in app delegate, it works but now im looking to remove the text completely for back button.
UIImage * backButtonImage = [UIImage imageNamed: #"BackButtonGrey.png"];
backButtonImage = [backButtonImage stretchableImageWithLeftCapWidth: 15.0 topCapHeight: 30.0];
[[UIBarButtonItem appearance] setBackButtonBackgroundImage: backButtonImage forState: UIControlStateNormal barMetrics: UIBarMetricsDefault];
Simply move the text vertically so far that it no longer appears. This can be done at app launch in your app delegate.
[[UIBarButtonItem appearance] setBackButtonTitlePositionAdjustment:UIOffsetMake(0, 20.f) forBarMetrics:UIBarMetricsDefault];
Normally this call is for tweaking the vertical text position which can vary depending on the font used. Here the text is moved far enough that it's no longer inside the Back button view, and so is clipped into non-existence.
I really don't think is a good practice for a developer to adjust the offset of the text in order to hide it.
A cleaner solution would be to just add to the navigation controller back button a new button where the title is an empty string. You should add this in the previous calling view controller in viewWillAppear (not the current one):
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:#"" style:UIBarButtonItemStylePlain target:nil action:nil];
self.navigationItem.backBarButtonItem = backButton;
[[UIBarButtonItem appearance] setBackButtonTitlePositionAdjustment:UIOffsetMake(-100.f, 0) forBarMetrics:UIBarMetricsDefault];
I just did it like this, worked fine for me :-)
UIImage *backButtonImage = [UIImage imageNamed:#"navigationBarBack.png"];
UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom];
[backButton setImage:backButtonImage
forState:UIControlStateNormal];
backButton.frame = CGRectMake(0, 0, backButtonImage.size.width, backButtonImage.size.height);
[backButton addTarget:self
action:#selector(popViewController)
forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *backBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
self.navigationItem.leftBarButtonItem = backBarButtonItem;
Do not use the appearance proxy. Instead, for every view controller, put this code into its viewDidLoad implementation:
UIImage * backButtonImage =
[UIImage imageNamed: #"BackButtonGrey.png"];
backButtonImage =
[backButtonImage stretchableImageWithLeftCapWidth: 15.0 topCapHeight: 30.0];
UIBarButtonItem* b =
[[UIBarButtonItem alloc]
initWithImage:backButtonImage
style:UIBarButtonItemStylePlain target:nil action:nil];
self.navigationItem.backBarButtonItem = b;
That will cause the next view controller pushed onto the navigation stack to have a back button consisting of just the image.
(However, I should point out that stretchableImageWithLeftCapWidth:... is deprecated. You should be using resizableImage....)
To set a backbutton text, you set a new backbutton to the current viewController before pushing or presenting then new one which would show the text of the backbutton:
In your current viewController (not the new one which will show the back-button):
vc = [[MyNewViewController alloc]initWith...];
vc.title = #"New ViewController";
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc]initWithTitle:#"Back" style:UIBarButtonItemStylePlain target:nil action:nil];
[self.navigationController pushViewController:vc animated:YES];
So if you want to remove the text, just use #"" as a title for the new backbutton.
To set a backbutton-icon for the entire app, use the following code in your appDelegate class. Not every icon fits perfectly, so if you have to move it around a little, you can use the "backInsets". In my example the icon will move 2px down.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
...
...
[self customBackButtonIcon];
return YES;
}
- (void)customBackButtonIcon
{
UIEdgeInsets backInsets = UIEdgeInsetsMake(0, 0, -2, 0);
UIImage *backImg = [[[UIImage imageNamed:#"back_button_white"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] imageWithAlignmentRectInsets:backInsets];
[[UINavigationBar appearance] setBackIndicatorImage:backImg];
[[UINavigationBar appearance] setBackIndicatorTransitionMaskImage:backImg];
}
Tested with iOS9
UIBarButtonItem *newBackButton =
[[UIBarButtonItem alloc] initWithTitle:#""
style:UIBarButtonItemStylePlain
target:nil
action:nil];
[[self navigationItem] setBackBarButtonItem:newBackButton];
Perfect solution globally
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
UIBarButtonItem.appearance().setTitleTextAttributes([NSForegroundColorAttributeName:UIColor.clearColor()], forState: UIControlState.Normal)
UIBarButtonItem.appearance().setTitleTextAttributes([NSForegroundColorAttributeName:UIColor.clearColor()], forState: UIControlState.Highlighted)
return true
}

IOS Custom UIBarbuttonItem change position in detail view

I'm trying to customize my navigationbar's UIBarbuttonItem so that I'm using this im my Appdelegate.m
// didFinishLaunchingWithOptions:
{
UIImage *navBarImage = [UIImage imageNamed:#"nav-bar.png"];
[[UINavigationBar appearance] setBackgroundImage:navBarImage
forBarMetrics:UIBarMetricsDefault];
[[UINavigationBar appearance] setTitleVerticalPositionAdjustment:5
forBarMetrics:UIBarMetricsDefault];
UIImage *barButtonSave = [[UIImage imageNamed:#"nav-bar-button.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 2, 0, 2)];
[[UIBarButtonItem appearance] setBackgroundImage:barButtonSave
forState:UIControlStateNormal
style:UIBarButtonItemStyleDone
barMetrics:UIBarMetricsDefault];
[[UIBarButtonItem appearance] setBackgroundVerticalPositionAdjustment:5 forBarMetrics:UIBarMetricsDefault];
return YES;
}
When I'm done with this I just place a UIBarbuttonItem with Storyboard and I'm done.
The point is I noticed that the "Save" button changes between my views!
It looks like is moving down few pixels in my DetailView:
Why is That?
I still don't know why. but I solved giving my custom UIbarbuttonItem image the 30px default height.
[see similar issue UIBarButtonItem shifting downwards after a UINavigationController push

iOS navigationbar setBackBarButtonItem to custom button

I need some assistance with how to customize 'backBarButtonItem'
And no I dont want to use the LeftBarButtomItem since I want to inherit the style and keep the transition from the 'BackBarButtom'
Okey, so what I got is:
UIBarButtonItem* barbtnItem = [[UIBarButtonItem alloc]initWithCustomView: [ArrivalProto ArrivalBtnTypeBack]];
[ArrivalProto ArrivalBtnTypeBack] gives me back a custom UIbutton with both a setBackgroundImage an a setImage.
And then all I want to do is to add this to customize the BackBarButton:
[self.navigationItem setBackBarButtonItem: barbtnItem];
But nooo. Just the the plain normal backbutton :(((
While this seems to work:
//self.navigationItem setLeftBarButtonItem:barbtnItem];
And this as well:
UIImage *btnTrnspBgrImg30 = [[UIImage imageNamed:#"trspBlackBtn30"]resizableImageWithCapInsets:UIEdgeInsetsMake(0, 5, 0, 5)];
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:btnTrnspBgrImg30 forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
Info:
[self.navigationItem setBackBarButtonItem: <#(UIBarButtonItem *)#>];
[self.navigationItem setLeftBarButtonItem:<#(UIBarButtonItem *)#>]
As of iOS5 we have an excellent new way of customizing the appearance of almost any control using the appearance proxy, i.e. [UIBarButtonItem appearance]. The appearance proxy allows you to create application wide changes to the look of controls. Below is an example of a custom back button created with the appearance proxy.
Use the example code below to create a back button with custom images for normal and highlighted states. Call the following method from you appDelegate's application:didFinishLaunchingWithOptions:
- (void) customizeAppearance {
UIImage *i1 = [[UIImage imageNamed:#"custom_backButton_30px"]
resizableImageWithCapInsets:UIEdgeInsetsMake(0, 15, 0, 6)];
UIImage *i2 = [[UIImage imageNamed:#"custom_backButton_24px"]
resizableImageWithCapInsets:UIEdgeInsetsMake(0, 15, 0, 6)];
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:i1
forState:UIControlStateNormal
barMetrics:UIBarMetricsDefault];
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:i2
forState:UIControlStateNormal
barMetrics:UIBarMetricsLandscapePhone];
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:i1
forState:UIControlStateHighlighted
barMetrics:UIBarMetricsDefault];
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:i2
forState:UIControlStateHighlighted
barMetrics:UIBarMetricsLandscapePhone];
}
This is just a quick example. Normally you would want to have separate images for normal and highlighted (pressed) state.
If you are interested in customizing the appearance of other controls, some good examples can be found here: http://ios.biomsoft.com/2011/10/13/user-interface-customization-in-ios-5/

IOS customized navigation back button is not working

I tried the following in my view controller. Didn't work. I am using Storyboard.
[super viewDidLoad];
UIImage *backImage = [UIImage imageNamed:#"Back.png"] ;
UIBarButtonItem *backButton=[[UIBarButtonItem alloc]initWithImage:backImage style: (UIBarButtonItemStyleBordered) target:nil action:nil];
backButton.title=#"TEST";
[self.navigationItem setBackBarButtonItem:backButton];
Please help. Thanks.
Try
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:[UIImage imageNamed:#"someimage.png"] forState:UIControlStateNormal barMetrics:UIBarMetricsDefault].
try this one this will solve your image problem
UIImage *backImage = [[UIImage imageNamed:#"Back.png"]resizableImageWithCapInsets:UIEdgeInsetsMake(0, 5, 0, 5)];
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:backImage forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
May this will solve your problem.
Happy Coding :)

Resources