1. UINavigationController 视图控制器
视图层次结构
目录结构
功能
- UINavigationController 视图控制器;
- 显示/隐藏导航栏和工具栏;
- 视图入栈和出栈;
- 导航栏样式;
- 自定义导航按钮;
功能代码
-
AppDelegate.m 文件:
初始化 UINavigationController 对象时,传入UIVIewController 实例对象作为根视图控制器。再将 UINavigationController 对象设置为 UIWindow 对象的根视图控制器。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; // 实例化第一个视图控制器对象 ViewController1 *firstViewController = [[ViewController1 alloc] initWithNibName:NSStringFromClass([ViewController1 class]) bundle:nil]; // 初始化导航视图控制器对象 _navigationController = [[UINavigationController alloc] initWithRootViewController:firstViewController]; // 将导航视图控制器对象,设置为当前窗口的根视图控制器 self.window.rootViewController = _navigationController; self.window.backgroundColor = [UIColor whiteColor]; [self.window makeKeyAndVisible]; return YES; }
-
ViewController1.m 文件
- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // 设置当前视图的标题 self.title = @"the first View"; // 设置当前视图右上角的导航按钮标题,以及点击事件 self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"SecondView" style:UIBarButtonItemStylePlain target:self action:@selector(gotoSecondView)]; } return self; } // 添加监听点击事件方法 - (void)gotoSecondView { // 初始化第二个视图控制器对象 ViewController2 *secondViewController = [[ViewController2 alloc] initWithNibName:NSStringFromClass([ViewController2 class]) bundle:nil]; // 将第二个视图控制器,压入导航视图控制器中,实现页面的跳转。 [self.navigationController pushViewController:secondViewController animated:YES]; }
执行结果
显示/隐藏导航栏、工具栏
// 隐藏当前视图控制器的顶部导航栏
[self.navigationController setNavigationBarHidden:YES];
// 隐藏底部工具栏
[self.navigationController setToolbarHidden:YES];
视图入栈和出栈;
- (void)pushView {
// 实例化第二个视图控制器
ViewController2 *secondViewController = [[ViewController2 alloc] initWithNibName:NSStringFromClass([ViewController2 class]) bundle:nil];
// 把视图控制器,push到导航视图里,相当于入栈操作
[self.navigationController pushViewController:secondViewController animated:YES];
}
- (void)popView {
// 当前视图控制器,将从导航视图控制器堆栈中移除,并返回至上一视图,相当于出栈操作
[self.navigationController popViewControllerAnimated:YES];
}
- (void)gotoIndexView {
// 根据导航视图控制器中的全局序号,查找堆栈中指定序号的视图控制器
UIViewController *viewController = [[self.navigationController viewControllers] objectAtIndex:2];
// 然后跳转至该视图控制器
[self.navigationController popToViewController:viewController animated:YES];
}
- (void)gotoRootView {
// 导航视图控制器中的所有子视图控制器,都将全部出栈,从而跳转到根视图控制器。
[self.navigationController popToRootViewControllerAnimated:YES];
}
- 子视图退出到某个指定的父视图
for (UIViewController *controller in self.navigationController.viewControllers) {
BOOL isKindOfClass = [controller isKindOfClass:[FisrtViewController class]];
if (isKindOfClass) {
[self.navigationController popToViewController:controller animated:YES];
}
}
导航栏样式
- 设置导航栏样式
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
// 设置顶部导航区的提示文字
self.navigationItem.prompt = @"Loading";
// 设置导航栏背景是否透明
self.navigationController.navigationBar.translucent = NO;
// 设置导航栏系统样式
self.navigationController.navigationBar.barStyle = UIBarStyleBlack;
// 设置导航按钮文本颜色。
self.navigationController.navigationBar.tintColor = [UIColor greenColor];
// 显示底部工具栏
[self.navigationController setToolbarHidden:NO];
}
- 设置导航栏标题&颜色
self.navigationItem.title = @"首页";
[self.navigationController.navigationBar setTitleTextAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:17.0f],NSForegroundColorAttributeName:ThemeColor}];
- 自定义导航按钮:左侧按钮、右侧按钮、中间标题;
- (void)viewDidLoad {
[super viewDidLoad];
// --------------------------------------------
// 实例化一个工具条按钮对象,它将作为我们新的导航按钮
UIBarButtonItem *leftButton = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemAdd
target:self
action:@selector(showAlert)];
// 将导航栏左侧按钮,设置为新的工具条按钮对象
self.navigationItem.leftBarButtonItem = leftButton;
// --------------------------------------------
// 同样为导航栏右侧的导航按钮,设置新的样式
UIBarButtonItem *rightButton = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemPlay
target:self
action:@selector(gotoSecondView)];
self.navigationItem.rightBarButtonItem = rightButton;
// --------------------------------------------
// 创建一个视图对象,它将作为我们导航栏的标题区
UIView *titleView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 30)];
[titleView setBackgroundColor:[UIColor brownColor]];
// 新建一个标签对象,它将显示标题区的标题文字
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(70, 0, 100, 30)];
label.text = @"Title";
[titleView addSubview:label];
// 将视图对象设置为导航栏的标题区
self.navigationItem.titleView = titleView;
}
- 调整左上角返回按钮的边框距离
/// 直接设置
@property(nullable, nonatomic,strong) UIBarButtonItem *leftBarButtonItem;
大部分情况下,我们需要指定左边返回按钮距离左边框的距离,可以如下设定:
// 【方法一】把系统返回按钮替换成了 UIButton
UIButton *backBt = [UIButton buttonWithType:UIButtonTypeSystem];
backBt.frame = CGRectMake(0, 0, 20, 20);
[backBt setBackgroundImage:[UIImage imageNamed:@"back"]
forState:UIControlStateNormal];
[backBt addTarget:self
action:@selector(backToRootViewController)
forControlEvents:UIControlEventTouchUpInside];
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backBt];
// 【方法二】在系统的返回按钮左侧加了一个带宽度的 Item
UIBarButtonItem *leftItem = [[UIBarButtonItem alloc]
initWithImage:[UIImage imageNamed:@"back"]
style:UIBarButtonItemStylePlain
target:self
action:@selector(backToRootViewController)];
UIBarButtonItem *fixedItem = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace
target:nil
action:nil];
// 设置边框距离,可以根据需要调节
fixedItem.width = -16;
self.navigationItem.leftBarButtonItems = @[fixedItem, leftItem];
- 全局属性设置
// 设置导航栏背景色
[[UINavigationBar appearance] setBarTintColor:[UIColor whiteColor]];
// 设置导航项颜色
[[UINavigationBar appearance] setTintColor:ThemeColor];
// 隐藏返回按钮文字
[[UIBarButtonItem appearance] setBackButtonTitlePositionAdjustment:UIOffsetMake(0, -60) forBarMetrics:UIBarMetricsDefault];
UINavigationControllerDelegate
// 一般用于传递参数,或者做一些其它处理
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated;
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated;
隐藏/去掉导航栏返回按钮文字,只显示一个左箭头
// 方法一:全局设置
// 该方法就是把标题向上移动 60 px
// 设置/获取标题栏竖直位置偏移,UIBarMetricsDefault(竖屏)
[[UIBarButtonItem appearance] setBackButtonTitlePositionAdjustment:UIOffsetMake(0, -60) forBarMetrics:UIBarMetricsDefault];
// 方法二:
// 注意此法需要在前一界面内设置,而且不是全局的,但是下一个界面标题会居中
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc]
initWithTitle:@""
style:UIBarButtonItemStylePlain
target:self
action:nil];
- 用方法一隐藏返回按钮的文字以后,当上一个视图控制器的标题太长,会导致顶层视图控制器标题不居中显示的问题,修复的方法如下(建议做成 UIViewController 范畴(category)类):
// 如果有上个界面,将上个界面的title置为空,还是绕到方法二来了
- (void)resetBackButtonItem {
NSArray *viewControllerArray = [self.navigationController viewControllers];
long previousViewControllerIndex = [viewControllerArray indexOfObject:self] - 1;
UIViewController *previous;
if (previousViewControllerIndex >= 0) {
previous = [viewControllerArray objectAtIndex:previousViewControllerIndex];
previous.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc]
initWithTitle:@""
style:UIBarButtonItemStylePlain
target:self
action:nil];
}
}
- 方法二也可以把返回按钮的文字替换为自定义文字,上面是替换为空了。
UIBarButtonItem *leftItem = [[UIBarButtonItem alloc] initWithTitle:@"返回"
style:UIBarButtonItemStylePlain
target:self
action:nil];
self.navigationItem.backBarButtonItem = leftItem;
以上代码可以嵌入自定义的 UINavigationController
基类中:
/*
删除导航栏底部线条
推荐替代方法:位于 ChameleonDemo:该方法会把所有页面的底部线条删除
self.navigationController.hidesNavigationBarHairline = YES;
*/
- (void)removeUnderline {
[self.navigationBar setShadowImage:[UIImage new]];
}
// 执行此方法时,统一设置下一个视图控制器的返回按钮
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated {
// 第一个controller左button不确定, 其他controller左button为特定样式
if (self.viewControllers.count > 0) {
UIBarButtonItem *backBarButtonItem =
[[UIBarButtonItem alloc] initWithTitle:@"返回"
style:UIBarButtonItemStylePlain
target:self
action:nil];
viewController.navigationItem.backBarButtonItem = backBarButtonItem;
viewController.hidesBottomBarWhenPushed = YES; // 推入下一个视图控制器时隐藏TabBar
}
[super pushViewController:viewController animated:animated];
}
在导航栏上添加多个按钮
// 设置导航栏返回按钮
UIBarButtonItem *backBarButtonItem = [[UIBarButtonItem alloc]
initWithTitle:@"返回"
style:UIBarButtonItemStylePlain
target:self
action:nil];
self.navigationItem.backBarButtonItem = backBarButtonItem;
// 设置导航栏其他按钮
UIBarButtonItem *closeBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"关闭" style:UIBarButtonItemStylePlain target:self action:@selector(backToRootViewController)];
self.navigationItem.leftBarButtonItem = closeBarButtonItem;
// 设置左侧自定义按钮是否与返回按钮共同存在
self.navigationItem.leftItemsSupplementBackButton = YES;
参考
- 超简单!!! iOS 设置状态栏、导航栏按钮、标题、颜色、透明度,偏移等