更改navigationController的navigationBar的返回按钮的图片

今天遇到需要修改navigationController的返回按钮的图标的需求,网上提供了在controller的viewDidAppear方法中去修改返回按钮为自定义的类型,但是这样做并不是一个完美的解决办法,所以写下来方便后来的人


首先需要自定义UINavigationController,并成为自己的代理,在willShowViewController方法中隐藏原本的返回按钮,并添加自定义的item,并将UIButton作为自定义view嵌套进item中,同时为了偏移按钮的位置,还需要添加一个UIBarButtonSystemItemFixedSpace类型的barButtonItem,这个控件可以偏移返回按钮的位置


#pragma mark -UINavigationControllerDelegate

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated{


//  如果是根视图,则不添加返回按钮

    if (viewController == self.childViewControllers[0] || viewController.navigationItem.hidesBackButton) {

        return;

    }

    

//  隐藏系统默认返回按钮

    viewController.navigationItem.hidesBackButton = true;

    

//  定义自定义的button,设置图片为自己想设置的返回按钮图片,并嵌套进一个UIBarButtonItem中

    UIButton *backButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 35, 35)];

    [backButton setBackgroundImage:[UIImage imageNamed:@"返回"] forState:UIControlStateNormal];

    [backButton addTarget:self action:@selector(backBarButtonItemClicked) forControlEvents:UIControlEventTouchUpInside];

    UIBarButtonItem *backItem = [[UIBarButtonItem alloc]initWithCustomView:backButton];

    

//  再创建一个空白的UIBarButtonItem,通过设置他的宽度可以偏移其右侧的返回按钮的位置

    UIBarButtonItem *spaceItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];

    spaceItem.width = -10;

    

//  将两个UIBarButtonItem设置给当前的VC

    viewController.navigationItem.leftBarButtonItems = @[spaceItem,backItem];

}



同时不要忘记给自己创建的返回按钮添加一个监听事件

#pragma mark -private func

- (void)backBarButtonItemClicked{

    [self popViewControllerAnimated:true];

}



但是这样就没有返回手势了,需要恢复返回手势

在navigationCotroller的viewDidLoad方法中添加如下代码

    //  修复没有返回手势的问题

    __weak typeof(self) weakSelf= self;

    if([self respondsToSelector:@selector(interactivePopGestureRecognizer)]){

        self.interactivePopGestureRecognizer.delegate = weakSelf;

    }



为了防止在push的过程中触发pop事件导致崩溃,需要在push的时候禁用pop手势

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated{

    //  防止在push的时候触发pop手势导致导航栏崩溃

    //  如果当前正在pop,则禁用手势

    if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)]) {

        self.interactivePopGestureRecognizer.enabled = false;

    }

    [super pushViewController:viewController animated:animated];

}


并在页面加载出来之后恢复手势

- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated{

    

    //  修复没有返回手势的问题

    if([self respondsToSelector:@selector(interactivePopGestureRecognizer)]){

        self.interactivePopGestureRecognizer.enabled = true;

    }

}



现在我们有了返回手势了,但是另一个问题出现了,在手势触发的时候在navBar的左边或中间会出现一个label,如果手势完全完成还好,如果要是触发手势了但是没有让页面pop,navBar上就会出现一个为 ··· 的label

遍历了windows的subviews,发现了一个可疑的按钮好像与这个有关

    for (UIView *view in [UIApplication sharedApplication].keyWindow.subviews) {

        [HBShareTool allView:view];

    }

    NSLog(@"~~~~~~~~~~~");


+ (void)allView:(UIView *)superView{

    for (UIView *subView in superView.subviews) {

        [HBShareTool allView:subView];

        if (subView.class == [UILabel class]) {

            NSLog(@"title:%@",[(UILabel *)subView text]);

            if ([[(UILabel *)subView text] isEqualToString:@"Back"]) {

                [(UILabel *)subView setText:@""];

            }

            subView.x += 10;

        }

        if (subView.class == [UIButton class]) {

            NSLog(@"button title:%@",[(UIButton *)subView titleLabel].text);

            subView.x += 10;

        }

    }

}


执行了上述代码,结果如下

2016-01-12 14:18:04.362 CreaTee[1128:642104] title:FRAME

2016-01-12 14:18:04.362 CreaTee[1128:642104] title:FONT

2016-01-12 14:18:04.362 CreaTee[1128:642104] title:GRAFFITI

2016-01-12 14:18:04.363 CreaTee[1128:642104] title:PUZZLE

2016-01-12 14:18:04.363 CreaTee[1128:642104] title:DESIGNER  TECOMMEND

2016-01-12 14:18:04.365 CreaTee[1128:642104] title:START DIY

2016-01-12 14:18:04.366 CreaTee[1128:642104] title:公牛字母T

2016-01-12 14:18:04.366 CreaTee[1128:642104] title:@MONSTER

2016-01-12 14:18:04.366 CreaTee[1128:642104] title:79

2016-01-12 14:18:04.367 CreaTee[1128:642104] title:NEW/新品

2016-01-12 14:18:04.367 CreaTee[1128:642104] title:内部价:48

2016-01-12 14:18:04.368 CreaTee[1128:642104] title:公牛字母T

2016-01-12 14:18:04.368 CreaTee[1128:642104] title:@MONSTER

2016-01-12 14:18:04.369 CreaTee[1128:642104] title:79

2016-01-12 14:18:04.369 CreaTee[1128:642104] title:NEW/新品

2016-01-12 14:18:04.370 CreaTee[1128:642104] title:内部价:48

2016-01-12 14:18:04.370 CreaTee[1128:642104] title:复仇者联盟(31)

2016-01-12 14:18:04.370 CreaTee[1128:642104] title:Back

2016-01-12 14:18:04.372 CreaTee[1128:642104] button title:(null)

2016-01-12 14:18:04.373 CreaTee[1128:642104] button title:(null)

2016-01-12 14:18:04.374 CreaTee[1128:642104] button title:(null)

2016-01-12 14:18:04.375 CreaTee[1128:642104] button title:(null)

2016-01-12 14:18:04.376 CreaTee[1128:642104] button title:(null)

2016-01-12 14:18:04.377 CreaTee[1128:642104] button title:(null)



通过排除法,最可疑的就是为Back的title,这个按钮应该是navController的返回按钮的title,解决办法就是在navController的didShow代理方法中设置一下返回按钮的title

    UIBarButtonItem *barButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:self action:nil];

    viewController.navigationItem.backBarButtonItem = barButtonItem;

将系统的返回按钮替换之后,问题被解决了。


但是我们已经把他隐藏了,为什么还会出现在屏幕上呢?

估计有可能两个原因:

1.因为用了系统自带的返回手势,而手势响应的某些方法影响了backItem的隐藏属性,导致手势触发的时候系统的返回按钮被显示出来,或被添加到navBar上了。

2.当根层级的VC在画面上出现的时候,由于其backItem没有被隐藏,所以nav认为rootVC已经出现了,则取消了backItem的显示,但其实这时候我们的当前VC并没有被POP,而是刚刚触发手势的状态,这时候如果将当前VC放回原位,由于backItem已经被显示了,而且隐藏只是一个状态,并不会因为手势的取消而改变,出现的同时,页面上已经没有它的位置了,所以被显示为"···",因为宽度不够。也就是说,跟层级的VC的“出现”让系统以为我们要进行pop了,所以提前将rootVC的nav属性赋给了navBar,但实际情况是时机还没有到。


以上是两点我估测的结果,各位如果有正确答案欢迎指正。

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值