I know how to add back navigation button with image or change the tile but I haven't seen any example with background image and its title (#"back").
Can I add a custom UIButton with custom background image and title?
This, what I finally did in my code actually works!!!
Just update "forState" and "barMetrics" values for different appearances.
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:[UIImage imageNamed:#"myImage"] forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
I'm not sure what you mean by (#back) but here is how I was able to get an image in the back button and the the UINavigationBar:
[[UINavigationBar appearance] setBackgroundImage:[UIImage imageNamed:#"myLogo.png"] forBarMetrics:UIBarMetricsDefault];
UIImage *backButton = [[UIImage imageNamed:#"HeaderTest.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(12, 12, 12, 12)];
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:backButton forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
This is an ios 5 solution. Thank you to these sources:
http://www.whypad.com/posts/ios-5-problem-setting-image-for-uinavigationbar/1011/
http://iosdevelopertips.com/user-interface/ios-5-customize-uinavigationbar-and-uibarbuttonitem-with-appearance-api.html
Related
I'm having problems to create an custom nav bar like the Uber app.
I'm setting my button background image to:
UIImage *button44 = [[UIImage imageNamed:#"navButtonAdd"]
resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 0, 0)];
[[UIBarButtonItem appearance] setBackgroundImage:button44 forState:UIControlStateNormal
barMetrics:UIBarMetricsDefault];
But If I remove the text from the button on the xcode interface it disappear the image as well and also there is a padding on the right that starts repeating my image again.
Does anyone know how I could fix it?
This is the image I'm trying to use as a button
Thanks in advance
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"button"]]];
[self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:#"uberbar.png"] forBarMetrics:UIBarMetricsDefault];
If I'm not mistaken you need a custom view on the UIBarButtonItem. So you could get the appearance proxy, set the image for the controller, or instead customize the image directly. That padding is a matter of photoshopping the graphic and set its dimensions correctly.
I use this code for customization UIBarButtonItems:
backImage = [UIImage imageNamed:#"barButtonImage"];
backImage = [backImage resizableImageWithCapInsets:UIEdgeInsetsMake(0.0f, 6.0f, 0.0f, 6.0f) resizingMode:UIImageResizingModeTile];
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:backImage forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[[UIBarButtonItem appearance] setBackgroundImage:backImage forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
All of navigation bars look fine
But toolbars have resized items in strange way:
All of UIBarButtonItems are defined in storyboard without any custom views. How can I remove this resizing?
I'm customizing the elements like navigation bar, tab bar and uibarbuttonitem using UIAppearance. It works very well except for a very strange behavior of the UIBarButtonItem elements. On the top level of the navigation controller hierarchy everything looks good, but if I push the next view controller, the UIBarButtonItem elements move a little bit downwards, but at the same time, the back button stays at its correct position. I attached two images to illustrate my problem.
1) First view controller in the navigation controller hierarchy
2) Second view controller in the navigation controller hierarchy
EDIT: The code
//Change navigation bar appearance
[[UINavigationBar appearance] setBackgroundImage:[UIImage imageNamed:#"GPNavigationBarBackground.png"] forBarMetrics:UIBarMetricsDefault];
[[UINavigationBar appearance] setShadowImage:[[UIImage alloc] init]];
[[UINavigationBar appearance] setShadowImage:[UIImage imageNamed:#"GPNavigationBarShadow.png"]];
[[UINavigationBar appearance] setTitleTextAttributes:
[NSDictionary dictionaryWithObjectsAndKeys:
[UIColor whiteColor], UITextAttributeTextColor,
[UIFont boldSystemFontOfSize:17], UITextAttributeFont,nil]];
[[UINavigationBar appearance] setTitleVerticalPositionAdjustment:2.f forBarMetrics:UIBarMetricsDefault];
UIImage *buttonBackground = [[UIImage imageNamed:#"GPNavigationBarButton.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 10, 0, 10)];
UIImage *buttonPressedBackground = [[UIImage imageNamed:#"GPNavigationBarButtonPressed.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 10, 0, 10)];
UIImage *backButtonBackground = [[UIImage imageNamed:#"GPNavigationBarBackButton.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 15, 0, 10)];
UIImage *backButtonPressedBackground = [[UIImage imageNamed:#"GPNavigationBarBackButtonPressed.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 15, 0, 10)];
[[UIBarButtonItem appearance] setBackgroundImage:buttonBackground forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[[UIBarButtonItem appearance] setBackgroundImage:buttonPressedBackground forState:UIControlStateHighlighted barMetrics:UIBarMetricsDefault];
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:backButtonBackground forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:backButtonPressedBackground forState:UIControlStateHighlighted barMetrics:UIBarMetricsDefault];
[[UIBarButtonItem appearance] setBackButtonBackgroundVerticalPositionAdjustment:1.f forBarMetrics:UIBarMetricsDefault];
[[UIBarButtonItem appearance] setBackgroundVerticalPositionAdjustment:1.f forBarMetrics:UIBarMetricsDefault];
[[UIBarButtonItem appearance] setTitlePositionAdjustment:UIOffsetMake(0, 1.f) forBarMetrics:UIBarMetricsDefault];
Well, after brooding on that problem, I finally solved it. The code above is absolutely correct. The only problem was the height of the background images for the UIBarButtonItem. The UIAppearance proxy lets you set all the graphics, but it doesn't allow you to alter the height of the UIBarButtonItem.
So, when customizing UIBarButtonItem, always remember that a
UIBarButtonItem can't be higher than 30pt. That means that custom artwork shouldn't exceed this size.
You can set background images that are higher than 30pt, but you will run into the same problem as stated above.
I've done the tutorial at my blog, so I know how to make a stretchable button that can display the bottom (stack) viewcontroller's title. But what I was hoping to do is have icons (like a house for HOME) and no text and not resize.
Using my custom image and this code below, I get a stretched version (not wanted) with title over top (not wanted) and it does tint/highlight when clicked (is good);
UIImage *backButtonImage = [UIImage imageNamed:#"backButton_30.png"];
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:backButtonImage forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
screen shot 1
Now, I've searched on here and read all the similar questions which return old answers, and have strange results for me. Here is the code I tried;
UIImage *backButtonImage = [UIImage imageNamed:#"backButton_30.png"];
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithImage:backButtonImage style:UIBarButtonItemStyleBordered target:nil action:nil];
self.navigationItem.backBarButtonItem = backButton;
This method doesn't stretch out my custom image button (is good), nor does it show text (what I want) however there is still the original blue button under it (WTF), and my custom button doesn't tint when clicked, only the blue button under it does!
screen shot 2
Please help, what am I missing?
*UPDATE
I've fixed it up a bit by using a resizable image. This forces it not to 'stretch'
UIImage *backButtonHomeImage = [[UIImage imageNamed:#"backButtonHomeWhite_30.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 0, 0)];
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:backButtonHomeImage forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
To fix the title showing up on the button I had to do
self.title =#" ";
Now this is a bit of a dirty fix but it seems to be working. The only problem left now is that I want a different back button on different views, and this method is causing some trouble; the last view that sets the button over-rides all other views. So in the end, depending on how you navigate through the app, returning to a previous view has the wrong back button and it never resets to the correct one.
UPDATE 2: POTENTIAL IDEA:
Would the following be a reasonable solution, or is it a hack that is liable to break something?
Hiding the default back button, like so,
[self.navigationItem setHidesBackButton:YES animated:NO];
...and then using a custom UIBarButtonItem, with a button in the style I actually want placed in the location of the back button, that sends a popViewControllerAnimated: message to the UINavigationController when tapped.
If you know of a more robust solution please do share, thank you.
Assuming that your current solution
UIImage *backButtonHomeImage = [[UIImage imageNamed:#"backButtonHomeWhite_30.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 0, 0)];
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:backButtonHomeImage forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
is acceptable to you, so the only problem left is how to update that button appeareance when you go back and forth between your views, an approach that could work is executing the code above in each of your controllers' viewWillAppear: method:
- (void)viewWillAppear:(BOOL)animated {
UIImage *backButtonHomeImage = [[UIImage imageNamed:#"backButtonHomeWhite_30.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 0, 0)];
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:backButtonHomeImage forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
}
If you are not satisfied with your current approach to having a custom UIBarButtonItem, the way to go is initializing your bar button item with initWithCustomView:. In this case, you can specify, e.g., a UIImageView with the image you like and it should work:
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithCustomView:[UIImageView ...]];
Hope this helps.
For iOS 5+ use [[UIBarButtonItem appearance] setBackButtonBackgroundImage:[UIImage imageNamed:#"someimage.png"] forState:UIControlStateNormal barMetrics:UIBarMetricsDefault].
Some code i used in a project:
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
UIImage *btnImg = [UIImage imageNamed:#"ButtonRetourInactive"];
[btn setImage:btnImg forState:UIControlStateNormal];
btn.frame = CGRectMake(0, 0, btnImg.size.width, btnImg.size.height);
[btn addTarget:self action:#selector(goBack:) forControlEvents:UIControlEventTouchUpInside];
self.navigationItem.leftBarButtonItem = [[[UIBarButtonItem alloc] initWithCustomView:btn] autorelease];
Note, this works on iOS 4 and 3 aswell.
if You are using story boards , its too easy . take a round rectangular button and place it on the navigation bar . then double click the button( on selecting,at first, it just shows attributes of bar button , but by selecting twice , you can change all its properties as if you are customizing a regular UI button) .
UIAppearance is no use in this case.
I tried to use:
- [UIBarButtonItem initWithCustomView:].
The view here you can add your background image and title, whatever you want.
i am using a MPMoviePlayerViewController inside my Project. I have defined the following appearance for UIButtons and UINavigationbar like so:
[[UIBarButtonItem appearanceWhenContainedIn:[UINavigationBar class], nil]
setBackgroundImage:[UIImage imageNamed:#"woodenBarButton"]
forState:UIControlStateNormal
barMetrics:UIBarMetricsDefault];
[[UINavigationBar appearance] setBackgroundImage:[UIImage imageNamed:#"navigationbarBackground"]
forBarMetrics:UIBarMetricsDefault];
So now MPMoviePlayerViewController is also using a navigation bar. The problem is now: The button uses the given appearance but the toolbar not => it looks crappy. So now i have the following questions:
Can i convince the UINavigationBar in MPMoviePlayerViewController to use the appearance?
OR can is remove appearance completely only for the MPMoviePlayerViewController.
I tried to access the button via playerViewController.navigationitem.leftbarbuttonitem and overwrite properties but that doesn't work.
Would be great if you can help me. Thanks.
have you tried also setting appearanceWhenContainedIn for MPMoviePlayerViewController? appearance and appearanceWhenContainedIn works both at the same time.
[[UINavigationBar appearance] setBackgroundImage:[UIImage imageNamed:#"navigationbarBackground"]
forBarMetrics:UIBarMetricsDefault];
[[UINavigationBar appearanceWhenContainedIn:[MPMoviePlayerViewController class], nil] setBackgroundImage:nil forBarMetrics:UIBarMetricsDefault];