If you've changed the tint colour of your UINavigationBar or you just want to get away from Apple's default UIBarButtonItem styles then UIAppearance can help you out again.
Please note that this is for iOS 6.0+. In iOS 5.0 you can only customise the Back button without having to create a subclass
UIImage* plainBtn = [[UIImage imageNamed:@"btn"] resizableImageWithCapInsets:UIEdgeInsetsMake(12, 12, 12, 12)];
UIImage* plainBtnHighlight = [[UIImage imageNamed:@"btn-high"] resizableImageWithCapInsets:UIEdgeInsetsMake(12, 12, 12, 12)];
UIImage* doneBtn = [[UIImage imageNamed:@"btn-done"] resizableImageWithCapInsets:UIEdgeInsetsMake(12, 12, 12, 12)];
UIImage* doneBtnHighlight = [[UIImage imageNamed:@"btn-done-high"] resizableImageWithCapInsets:UIEdgeInsetsMake(12, 12, 12, 12)];
// Set the background images for all plain style buttons
[[UIBarButtonItem appearance] setBackgroundImage:plainBtn forState:UIControlStateNormal style:UIBarButtonItemStylePlain barMetrics:UIBarMetricsDefault];
[[UIBarButtonItem appearance] setBackgroundImage:plainBtnHighlight forState:UIControlStateHighlighted style:UIBarButtonItemStylePlain barMetrics:UIBarMetricsDefault];
// Set the background images for all of our done style buttons
[[UIBarButtonItem appearance] setBackgroundImage:doneBtn forState:UIControlStateNormal style:UIBarButtonItemStyleDone barMetrics:UIBarMetricsDefault];
[[UIBarButtonItem appearance] setBackgroundImage:doneBtnHighlight forState:UIControlStateHighlighted style:UIBarButtonItemStyleDone barMetrics:UIBarMetricsDefault];
Documentation for this method is here: UIBarButtonItem - setBackgroundImage:forState:style:barMetrics:
Something to watch out for if you're doing custom text attributes for your UIBarButtonItem's. E.g.
[[UIBarButtonItem appearance] setTitleTextAttributes:attrsNormal forState:UIControlStateNormal];
[[UIBarButtonItem appearance] setTitleTextAttributes:attrsHighlighted forState:UIControlStateHighlighted];
This goes for all of your UIBarButtonItem's in your app. What this means is if you had a white plainBtn image and a very dark doneBtn image you may have to watch out what UITextAttributeTextColor you set. E.g. if you set a black colour then it might not be seen on the Done buttons.
One way I found to get around this is making your root view a UINavigationController and setting itself as a UINavigationControllerDelegate.
You can then implement the delegate method navigationController:willShowViewController:animated::
#pragma mark - UINavigationControllerDelegate
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
NSDictionary* attrs = @{UITextAttributeTextColor: [UIColor whiteColor]};
for (UIBarButtonItem* rightBarButton in viewController.navigationItem.rightBarButtonItems)
{
if (rightBarButton.style == UIBarButtonItemStylePlain || rightBarButton.style == UIBarButtonItemStyleDone)
{
[rightBarButton setTitleTextAttributes:attrs forState:UIControlStateNormal];
[rightBarButton setTitleTextAttributes:attrs forState:UIControlStateHighlighted];
}
}
}
It's kind of a cheat; but I haven't found a better solution to making sure your Plain and Done buttons have different title text attributes.