Custom back button in UINavigationController

2019-02-02 08:05发布

For an application I'm developing, I need to display a custom back button in a navigation bar. I have the button asset as a PNG image, and I'm writing this code:

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom];
    backButton.frame = CGRectMake(0, 0, 79, 29.0);
    [backButton setImage:[UIImage imageNamed:@"button_back.png"] forState:UIControlStateNormal];
    self.navigationItem.backBarButtonItem = [[[UIBarButtonItem alloc] initWithCustomView:backButton] autorelease];

}

When I push this view controller, the custom button does not show up, and instead I get the standard back button with the title of this view controller inside.

Things I already tried:

  1. Doubled check that the button backButton is created properly, by adding it to the view hierarchy. It displays properly.
  2. In the same method, changed the title property of the navigationItem and confirmed that it changes (as expected) the content of my back button.

Can anyone spot what I'm doing wrong? Did anyone succeed in using a custom image as the back button on with a UINavigationController?

10条回答
一纸荒年 Trace。
2楼-- · 2019-02-02 08:37

The backBarButtonItem property works as intended, but it will always add its standard button shape and color based on the navigation bar tint color.

You can customize the text, but not replace the image.

One workaround, as Andrew Pouliot suggested, is to use leftBarButtonItem instead, but I stuck to the standard button instead.

查看更多
乱世女痞
3楼-- · 2019-02-02 08:39

I'm reposting my solution from https://stackoverflow.com/a/16831482/171933:

I create a simple category on UIViewController:

UIViewController+ImageBackButton.h

#import <UIKit/UIKit.h>

@interface UIViewController (ImageBackButton)

- (void)setUpImageBackButton;

@end

UIViewController+ImageBackButton.m

#import "UIViewController+ImageBackButton.h"

@implementation UIViewController (ImageBackButton)

- (void)setUpImageBackButton
{
    UIButton *backButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 34, 26)];
    [backButton setBackgroundImage:[UIImage imageNamed:@"back_arrow.png"] forState:UIControlStateNormal];
    UIBarButtonItem *barBackButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
    [backButton addTarget:self action:@selector(popCurrentViewController) forControlEvents:UIControlEventTouchUpInside];
    self.navigationItem.leftBarButtonItem = barBackButtonItem;
    self.navigationItem.hidesBackButton = YES;
}

- (void)popCurrentViewController
{
    [self.navigationController popViewControllerAnimated:YES];
}

@end

Now all you have to do is #import UIViewController+ImageBackButton.h in either all of your view controllers or in a custom base view controller class that your other view controllers inherit from and implement the viewWillAppear: method:

- (void)viewWillAppear:(BOOL)animated
{
    [self setUpImageBackButton];
}

That's all. Now you have an image back button everywhere. Without a border. Enjoy!

查看更多
时光不老,我们不散
4楼-- · 2019-02-02 08:41

Simply create a UIBarButtonItem instead of an embedded UIButton in UIBarButtonItem. Works fine!

UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"button_back.png"] style:UIBarButtonItemStyleBordered target:nil action:nil];

self.navigationItem.backBarButtonItem = backButton; 
查看更多
仙女界的扛把子
5楼-- · 2019-02-02 08:42

Starting with iOS 5, this is simple:

[[UIBarButtonItem appearance]
            setBackButtonBackgroundImage:[UIImage imageNamed:@"back_button.png"]
            forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];

You can place that in your app delegate and it will set the background image to all back buttons in the app (for that control state and bar metrics, of course).

查看更多
Ridiculous、
6楼-- · 2019-02-02 08:42

Isn't the simplest solution just to design it from your storyboard with whatever image or colors you want, and just drag a new action to your controller?

Swift Code

@IBAction func backButton(sender: AnyObject) {
    self.navigationController?.popViewControllerAnimated(true)
}
查看更多
地球回转人心会变
7楼-- · 2019-02-02 08:46

Johannes Fahrenkrug's Answer works, but the back image would appear at a very wired position.

Here I found a better way to position the image at the right place:

Make Sure You Have a back image with size 24x24(@1x) , I call it backImage

Execute the following code when your app Launch

UINavigationBar.appearance().barTintColor = nil
UINavigationBar.appearance().backIndicatorImage = backImage
UINavigationBar.appearance().backIndicatorTransitionMaskImage = backImage
UIBarButtonItem.appearance().setBackButtonTitlePositionAdjustment(UIOffsetMake(0, -60), forBarMetrics: .Default)
查看更多
登录 后发表回答