在開發(fā)過程中,我們經(jīng)常遇到使用系統(tǒng)導(dǎo)航欄的功能,如何更改返回按鈕的樣式呢?
一、更改返回按鈕圖片
// 更換返回按鈕的圖片
UIImage *backButtonImage = [[UIImage imageNamed:@"bt_navigationBar_back"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
[UINavigationBar appearance].backIndicatorTransitionMaskImage = backButtonImage;
[UINavigationBar appearance].backIndicatorImage = backButtonImage;
// 返回按鈕的文字置空(在UINavigationController的子類或者分類categary)中添加該方法
- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPushItem:(UINavigationItem *)item {
UIBarButtonItem *back = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil];
item.backBarButtonItem = back;
return YES;
}
二、重寫返回按鈕
重寫返回按鈕一般是添加leftBarButtonItems。如果導(dǎo)航欄添加了leftBarButtonItems之后,會(huì)自動(dòng)隱藏返回按鈕backBarButtonItem。
// 返回按鈕
UIBarButtonItem *backBarButtonItem = [[UIBarButtonItem alloc] initWithImage:[[UIImage imageNamed:@"bt_navigationBar_back"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] style:UIBarButtonItemStylePlain target:self action:@selector(backAction)];
self.navigationItem.leftBarButtonItem = backBarButtonItem;
// 返回按鈕的回調(diào)方法
- (void)backAction {
}
三、攔截系統(tǒng)導(dǎo)航欄的返回按鈕監(jiān)聽事件
當(dāng)我們使用了系統(tǒng)的導(dǎo)航欄時(shí),默認(rèn)點(diǎn)擊返回按鈕是 pop 回上一個(gè)界面。但是在有時(shí)候,我們需要在點(diǎn)擊導(dǎo)航欄的返回按鈕時(shí)不一定要 pop 回上一界面,可能是其他的頁面,我們需要攔截返回按鈕的pop操作。
1、重寫返回按鈕
具體操作查看上面“二、重寫返回按鈕”。
缺點(diǎn):若重寫了某個(gè)界面的返回按鈕,感覺應(yīng)用整體就不統(tǒng)一了。而且每有一個(gè)界面有這個(gè)需求都需要重新自定義一個(gè)返回按鈕,顯得不優(yōu)雅,工作繁瑣。
2、為 UINavigationController 添加 category
//item將要push的時(shí)候調(diào)用,返回NO,則不能push
- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPushItem:(UINavigationItem *)item; // called to push. return NO not to.
//item已經(jīng)push后調(diào)用
- (void)navigationBar:(UINavigationBar *)navigationBar didPushItem:(UINavigationItem *)item; // called at end of animation of push or immediately if not animated
//item將要pop時(shí)調(diào)用,返回NO,不能pop
- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item; // same as push methods
//item已經(jīng)pop后調(diào)用
- (void)navigationBar:(UINavigationBar *)navigationBar didPopItem:(UINavigationItem *)item;
我們可以為 UINavigatonController 創(chuàng)建一個(gè) Category,來定制navigationBar: shouldPopItem: 的邏輯。
// UIViewController+BackButtonHandler.h
@protocol BackButtonHandlerProtocol <NSObject>
@optional
// 重寫下面的方法以攔截導(dǎo)航欄返回按鈕點(diǎn)擊事件,返回 YES 則 pop,NO 則不 pop
-(BOOL)navigationShouldPopOnBackButton;
@end
@interface UIViewController (BackButtonHandler) <BackButtonHandlerProtocol>
@end
// UIViewController+BackButtonHandler.m
@implementation UIViewController (BackButtonHandler)
@end
@implementation UINavigationController (ShouldPopOnBackButton)
- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item {
if([self.viewControllers count] < [navigationBar.items count]) {
return YES;
}
BOOL shouldPop = YES;
UIViewController* vc = [self topViewController];
if([vc respondsToSelector:@selector(navigationShouldPopOnBackButton)]) {
shouldPop = [vc navigationShouldPopOnBackButton];
}
if(shouldPop) {
dispatch_async(dispatch_get_main_queue(), ^{
[self popViewControllerAnimated:YES];
});
} else {
// 取消 pop 后,復(fù)原返回按鈕的狀態(tài)
for(UIView *subview in [navigationBar subviews]) {
if(0. < subview.alpha && subview.alpha < 1.) {
[UIView animateWithDuration:.25 animations:^{
subview.alpha = 1.;
}];
}
}
}
return NO;
}
使用時(shí),只需要在需要攔截返回按鈕事件的控制器中,應(yīng)用#import "UIViewController+BackButtonHandler.h",并重寫-(BOOL)navigationShouldPopOnBackButton方法即可。
- (BOOL)navigationShouldPopOnBackButton{
//攔截返回按鈕后做的處理
//返回NO(一定要返回NO)
return NO;
}