set custom back bar button universally with no tit

2019-02-10 10:18发布

问题:

I want to set custom back bar button for all controllers in the app. I tried using this:

[[UIBarButtonItem appearance] setBackButtonBackgroundImage:backButtonImage forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];

It sets the image. That's OK. But, what i really want to do is that, i just want a custom button for back bar button which does not contain any title etc. The code above works, but it adds automated titles and resizes the back bar button item. My need is to have a fixed frame, no-title back bar button item for all controllers in the app.

回答1:

I've resolved it. Just make a category over UIViewController and import it in prefix.pch file. Then write a method: customViewWillAppear: and swizzle it with viewWillAppear method:

+(void)load{

Method viewWillAppear = class_getInstanceMethod(self, @selector(customViewWillAppear:));

Method customViewWillAppear = class_getInstanceMethod(self, @selector(viewWillAppear:));
method_exchangeImplementations(viewWillAppear, customViewWillAppear);

}

Add the above method to that category class. Then implement your customViewWillAppear method like this:

-(void)customViewWillAppear:(BOOL)animated{
    [self customViewWillAppear:animated];
    if([self.navigationController.viewControllers indexOfObject:self] != 0  && !self.navigationItem.hidesBackButton){
        UIBarButtonItem *cancelBarButton = nil;
        UIButton* cancelButton = [UIButton buttonWithType:UIButtonTypeCustom];
        [cancelButton addTarget:self action:@selector(popViewControllerWithAnimation) forControlEvents:UIControlEventTouchUpInside];
        [cancelButton setBackgroundImage:[UIImage imageNamed:@"yourImage.png"] forState:UIControlStateNormal];
        [cancelButton sizeButtonToFit];

        cancelBarButton = [[UIBarButtonItem alloc] initWithCustomView:cancelButton];

        NSMutableArray * leftButtons = [NSMutableArray arrayWithObject:cancelBarButton];
        [leftButtons addObjectsFromArray:self.navigationItem.leftBarButtonItems];
        [self.navigationItem setLeftBarButtonItem:nil];
        [self.navigationItem setLeftBarButtonItems:leftButtons];
    }

    [self.navigationItem setHidesBackButton:YES];
}
-(void)popViewControllerWithAnimation{
    [self.navigationController popViewControllerAnimated:YES];
}

Now, for every controller in your code, you have a custom back button. This took me a lot of time to implement and figure out. Hope it'll help you guys all too.

EDIT: Please use the following code to support iOS7> back swipe feature;

UIImage *image = [UIImage imageForName:@"some_image"];
navBar.backIndicatorImage = [image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
navBar.backIndicatorTransitionMaskImage = [image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];

Create a base view controller and add the following code;

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil];
}


回答2:

I've had a similar problem before and I've searched everywhere for a solution.

The only one I've found, which works for your problem was to implement in EVERY view controller a UILeftBarButton which does the popping.

You can change the background image the way you're doing, but if you set the text to nil or empty text (""), you're button just won't show up.

You also can't change the View of the UIBackBarButton, only it's text (so no custom button).



回答3:

What i did, was set the backbutton title label alpha to zero, using appearance proxy.



回答4:

My code in ViewDidLoad:

// Set back button image
if ([[self.navigationController viewControllers] objectAtIndex:0] != self) {
    UIButton *btnBack = [UIButton buttonWithType:UIButtonTypeCustom];
    btnBack.frame = CGRectMake(0,0,38,30);
    [btnBack setBackgroundImage:[UIImage imageNamed:@"NavigationBarBackButton"] forState:UIControlStateNormal];
    [btnBack addTarget:self.navigationController action:@selector(popViewControllerAnimated:) forControlEvents:UIControlEventTouchUpInside];
    UIBarButtonItem *leftBtn = [[UIBarButtonItem alloc] initWithCustomView:btnBack];
    [self.navigationItem setLeftBarButtonItem:leftBtn];
}


回答5:

You could write a category like this,

//
//  UINavigationItem+BarAditions.h
//
//  Created by Satheeshwaran on on 7/5/13.
//


#import <Foundation/Foundation.h>


@interface UINavigationItem (PersonaAddition)

- (void)setCustomBackButton;

@end


//
//  UINavigationItem+BarAditions.m
//
//  Created by Satheeshwaran on on 7/5/13.
//

#import "UINavigationItem+PersonaAddition.h"


@implementation UINavigationItem (PersonaAddition)

- (void)setCustomBackButton 
{
    //customize ur back button here.
    UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom];
    backButton.frame=CGRectMake(0, 0, 60, 30);
    [backButton addTarget:target action:@selector(didPressLeftItem:) forControlEvents:UIControlEventTouchUpInside];
    UIBarButtonItem *barItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
    self.leftBarButtonItem = barItem;    

}

and import this category in all ur files and call the setCustomBackButton in all ur classes. This works fine for me, even in iOS 7.

In ViewDidLoad of all ur classes.

- (void)viewDidLoad
{
    [super viewDidLoad];

    [self.navigationItem setCustomBackButton];

}


回答6:

try this code:

UIButton *tempbtn = [[UIButton alloc] init];
[tempbtn setImage:[UIImage imageNamed:@"testbtn.png"] forState:UIControlStateNormal];
UIBarButtonItem *temp = [[UIBarButtonItem alloc] initWithCustomView:tempbtn];
self.navigationItem.rightBarButtonItem = temp;