自定义 UINavigationBar 返回按钮

在做项目的过程中,很多时候都需要自定义UINavigationBar的返回按钮,有些人选择直接写一个UIView作为NavigationBar,有些也会选择修改系统UINavigationBar上的backBarButtonItem或者leftBarButtonItem。本文讲解的是后一种,即:修改系统UINavigationBar上的leftBarButtonItem。


环境信息
Mac OS X 10.10.1
Xcode 6.1.1
iOS 8.1

正文

一. 理论

首先需要知道的是,苹果对于修改UINavigationBar按钮的要求。关于返回按钮的样式有以下三个特点(A push B):

在官网文档的UINavigationBar部分,可以看到以下描述:

Pushing a navigation item displays the item’s title in the center on the navigation bar. The previous top navigation item (if it exists) is displayed as a back button on the left side of the navigation bar. If the new top item has a left custom view, it is displayed instead of the back button.

表达的意思如下:

推出一个控制器以后,title会显示到UINavigationBar的中间。关于BarButton的特点差不多可以分为三种情况:

  1. 如果A自定义了BackBarButtonItem,那么B会显示A的返回按钮;

  2. 如果B自定义了LeftBarButtonItem,那么B会显示自己的返回按钮;

  3. 如果A未定义BackBarButtonItem,B也未定义LeftBarButtonItem,那么B会显示系统的返回按钮。

为了左侧按钮的定义更灵活,我选择了给B自定义LeftBarButtonItem这种方式修改UINavigationBar的返回按钮。

二. 框架与封装

因为每一个需要返回按钮的UIViewController都要自定义LeftBarButtonItem,所以我们给这些UIViewController一个父类BackBaseViewController,在父类中统一修改LeftBarButtonItem的样式。以下是BackBaseViewController.m的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

@implementation BackBaseViewController

- (void)viewDidLoad {

[super viewDidLoad];
// Do any additional setup after loading the view.

// 初始化一个返回按钮
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 40, 40)];
// 为返回按钮设置图片样式
[button setImage:[UIImage imageNamed:@"back"] forState:UIControlStateNormal];
// 设置返回按钮触发的事件
[button addTarget:self action:@selector(backBarButtonPressed:) forControlEvents:UIControlEventTouchUpInside];

// 初始化一个BarButtonItem,并将其设置为返回的按钮的样式
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithCustomView:button];
// 将BarButtonItem添加到LeftBarButtonItem上
self.navigationItem.leftBarButtonItem = backButton;
}

#pragma mark - BarButton Pressed

/**
* 返回按钮触发的事件
*
* @param sender 返回按钮
*/
- (void)backBarButtonPressed:(UIButton *)sender {

[self.navigationController popViewControllerAnimated:YES];
}

@end

需要有自定义返回按钮样式的UIViewController全部集成BackBaseViewController即可。

对此,我写了一个Demo,下载地址如下:

https://github.com/saitjr/CustomUINavigationBarBackButtonDemo.git