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条回答
小情绪 Triste *
2楼-- · 2019-02-02 08:53

See this answer here: How to create backBarButtomItem with custom view for a UINavigationController

You just need to set the backBarButtonItem property on the navigationController before pushing the viewController. Setting the backBarButtonItem property in the viewController's viewDidLoad method (for example) doesn't work.

查看更多
疯言疯语
3楼-- · 2019-02-02 08:58

I do not think that ViewController itself should know anything about its back button According to OOP this is the responsibility of containerViewController in which your view controller is inserted, for example UINavigationController.

Subclass your NavigationController and overload in it superClass method like this:

@implementation STONavigationController

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    [super pushViewController:viewController animated:animated];
    if ([self.viewControllers indexOfObject:viewController] != NSNotFound &&
        [self.viewControllers indexOfObject:viewController] > 0){
        UIImage *img = [UIImage imageNamed:@"back-1"];
        UIButton *backButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, img.size.width * 2, img.size.height * 2)];
        [backButton setBackgroundImage:img forState:UIControlStateNormal];
        UIBarButtonItem *barBackButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
        [backButton addTarget:self action:@selector(popCurrentViewController) forControlEvents:UIControlEventTouchUpInside];
        viewController.navigationItem.leftBarButtonItem = barBackButtonItem;
        viewController.navigationItem.hidesBackButton   = YES;
    }
}

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

@end 
查看更多
Deceive 欺骗
4楼-- · 2019-02-02 08:58

As @pgb suggested you can use leftBarButtonItem instead of back button item. And to remove the default back button item set it to nil like follows;

navigationController?.navigationBar.backIndicatorImage = nil
navigationController?.navigationBar.backIndicatorTransitionMaskImage = nil

let button = UIButton.init(type: .custom)
button.imageView?.contentMode = UIViewContentMode.scaleAspectFit
button.setImage(UIImage.init(named: "top_back"), for: UIControlState.normal)
button.frame = CGRect.init(x: 0, y: 0, width: 75, height: 50) 
button.addTarget(self, action: #selector(handleBackButton), for: .touchUpInside)

let barButton = UIBarButtonItem.init(customView: button)
self.navigationItem.leftBarButtonItem = barButton
查看更多
5楼-- · 2019-02-02 09:00

Confusingly backBarButtonItem is not what you're looking for.

It just controls the title on the back button for the next view controller. What you want is to set the leftBarButtonItem to your custom back button.

查看更多
登录 后发表回答