在开发过程中,我们经常遇到使用系统导航栏的功能,如何更改返回按钮的样式呢?
一、更改返回按钮图片
// 更换返回按钮的图片
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。如果导航栏添加了leftBarButtonItems之后,会自动隐藏返回按钮backBarButtonItem。
// 返回按钮
UIBarButtonItem *backBarButtonItem = [[UIBarButtonItem alloc] initWithImage:[[UIImage imageNamed:@"bt_navigationBar_back"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] style:UIBarButtonItemStylePlain target:self action:@selector(backAction)];
self.navigationItem.leftBarButtonItem = backBarButtonItem;
// 返回按钮的回调方法
- (void)backAction {
}
三、拦截系统导航栏的返回按钮监听事件
当我们使用了系统的导航栏时,默认点击返回按钮是 pop 回上一个界面。但是在有时候,我们需要在点击导航栏的返回按钮时不一定要 pop 回上一界面,可能是其他的页面,我们需要拦截返回按钮的pop操作。
1、重写返回按钮
具体操作查看上面“二、重写返回按钮”。
缺点:若重写了某个界面的返回按钮,感觉应用整体就不统一了。而且每有一个界面有这个需求都需要重新自定义一个返回按钮,显得不优雅,工作繁琐。
2、为 UINavigationController 添加 category
//item将要push的时候调用,返回NO,则不能push
- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPushItem:(UINavigationItem *)item; // called to push. return NO not to.
//item已经push后调用
- (void)navigationBar:(UINavigationBar *)navigationBar didPushItem:(UINavigationItem *)item; // called at end of animation of push or immediately if not animated
//item将要pop时调用,返回NO,不能pop
- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item; // same as push methods
//item已经pop后调用
- (void)navigationBar:(UINavigationBar *)navigationBar didPopItem:(UINavigationItem *)item;
我们可以为 UINavigatonController 创建一个 Category,来定制navigationBar: shouldPopItem: 的逻辑。
// UIViewController+BackButtonHandler.h
@protocol BackButtonHandlerProtocol <NSObject>
@optional
// 重写下面的方法以拦截导航栏返回按钮点击事件,返回 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 后,复原返回按钮的状态
for(UIView *subview in [navigationBar subviews]) {
if(0. < subview.alpha && subview.alpha < 1.) {
[UIView animateWithDuration:.25 animations:^{
subview.alpha = 1.;
}];
}
}
}
return NO;
}
使用时,只需要在需要拦截返回按钮事件的控制器中,应用#import "UIViewController+BackButtonHandler.h",并重写-(BOOL)navigationShouldPopOnBackButton方法即可。
- (BOOL)navigationShouldPopOnBackButton{
//拦截返回按钮后做的处理
//返回NO(一定要返回NO)
return NO;
}
网友评论