iOS 导航栏-返回按钮-自定义

2019-04-26  本文已影响0人  光之盐汽水

在开发过程中,我们经常遇到使用系统导航栏的功能,如何更改返回按钮的样式呢?

一、更改返回按钮图片

// 更换返回按钮的图片
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;
}
上一篇下一篇

猜你喜欢

热点阅读