I am trying to set the background image for back button in normal and highlighted states.
- (void)configureBackButtonInNavigationItem:(UINavigationItem *)item
{
UIBarButtonItem *backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"back"
style:UIBarButtonItemStyleBordered target:nil action:NULL];
[backBarButtonItem setTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColor whiteColor]} forState:UIControlStateNormal];
[backBarButtonItem setTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColor orangeColor]} forState:UIControlStateHighlighted];
// white arrow image
UIImage *normalImage = [[[UIImage imageNamed:@"btn_normal"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] resizableImageWithCapInsets:UIEdgeInsetsMake(0.f, 17.f, 0.f, 0.f)];
// orange arrow image
UIImage *pressedImage = [[[UIImage imageNamed:@"btn_on_press"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] resizableImageWithCapInsets:UIEdgeInsetsMake(0.f, 17.f, 0.f, 0.f)];
[backBarButtonItem setBackButtonBackgroundImage:normalImage
forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[backBarButtonItem setBackButtonBackgroundImage:pressedImage
forState:UIControlStateHighlighted barMetrics:UIBarMetricsDefault];
[backBarButtonItem setBackgroundImage:normalImage
forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[backBarButtonItem setBackgroundImage:pressedImage
forState:UIControlStateHighlighted barMetrics:UIBarMetricsDefault];
NSLog(@"NORMAL: %@ HIGHLIGHTED: %@", [backBarButtonItem backButtonBackgroundImageForState:UIControlStateNormal barMetrics:UIBarMetricsDefault],
[backBarButtonItem backButtonBackgroundImageForState:UIControlStateHighlighted barMetrics:UIBarMetricsDefault]);
item.backBarButtonItem = backBarButtonItem;
NSLog(@"NORMAL: %@ HIGHLIGHTED: %@", [backBarButtonItem backButtonBackgroundImageForState:UIControlStateNormal barMetrics:UIBarMetricsDefault],
[backBarButtonItem backButtonBackgroundImageForState:UIControlStateHighlighted barMetrics:UIBarMetricsDefault]);
}
The output is following:
NORMAL: <_UIResizableImage: 0x16b55e10> HIGHLIGHTED: <_UIResizableImage: 0x16b593d0>
NORMAL: <_UIResizableImage: 0x16b55e10> HIGHLIGHTED: <_UIResizableImage: 0x16b593d0>
But observed result for highlighted state is just dimming of what was set to the normal state instead of using the correct highlighted image.
Normal:
Highlighted (Arrow is still white, button is dimmed unexpectedly):
Please do not post answers regarding usage of leftBarButtonItem
or UIButton
as custom view. Both these approaches break swipe-to-go-back behaviour available on iOS 7.
UPD: filled radar #17481106 regarding this issue.
UPD2: radar #17481106 fixed in iOS 8.
You didn't want a custom view because it would break the swiping, but you should add this line.
Your code would be something like below.
In addition to l0gg3r's answer, you can make a subclass of UINavigationBar where you can implement l0gg3r's logic and customize your back button.
After which you just have to set the class name to your navigationBar from storyboard.
Something like this:
Then:
Here you go. Thats it! Now you can just copy/paste that class into any project you want and just set class name from storyboard :)
Currently Apple has bug on
interactivePopGestureRecognizer
(which makes to freeze navigation controller's view after swiping back on push animation, you will seenested pop animation can result in corrupted navigation bar
warning in console), by the way, we can make a small hack to work around that bug.Here is a solution that works fine for me,
Subclass a NavigationController class and make it to delegate the gesture
When the user starts swiping backwards in the middle of a transition, the pop events stack up and "corrupt" the navigation stack. My workaround is to temporarily disable the gesture recognizer during push transitions, and enable it again when the new view controller loads. Again, this is easier with a UINavigationController subclass.
After this, you can calmly use
item.leftBarButtonItem
andUIButton
as custom view.