2018-07-11 UINavigationController和UINavigationBar

在做View Controller的生命周期的时候,由于要用到UINavigationController,就干脆继续学习了一波这个知识点,参考了这篇文章

一.定义

UINavigationController(导航控制器)是一个容器控制器,其内部有多个UIViewController(视图控制器)的内容,我们可以通过UINavigationControllerview属性获取到其自身的视图,在该视图上面有一个位于界面顶部的UINavigationBar(导航栏)和位于界面底部的默认隐藏的UIToolbar(工具栏),以及一个位于界面中间部分的UIViewControllerview

2018-07-11 UINavigationController和UINavigationBar_第1张图片
UINavigationController层级结构

当用户在UINavigationController的层级结构中来回切换的时候,UINavigationBarUIToolbar的内容会随之发生变化,但是其本身并不会发生变化,唯一发生变化的就是位于界面中间部分的UIViewControllerview

二.UIViewController堆栈的管理

UINavigationController通过其管理的UIViewController堆栈来决定展示在UINavigationController中间部位的内容,该内容由位于UIViewController堆栈的栈顶位置的UIViewController决定。

下图的View ControllersUIViewController堆栈navigationBar是位于顶部的UINavigationBartoolBar是位于底部的UIToolbar

2018-07-11 UINavigationController和UINavigationBar_第2张图片
UIViewController堆栈

根据栈的定义,如果我们要实现这个栈的内容,既可以用push和pop对UIViewController进行操作,也可以直接设置UIViewController堆栈的内容。

1.push

//push
//方法一
/*
 * 参数一: UIViewController, 该参数不可以使用UITabBarController的实例
 * 参数二: 是否执行动画
 */
[navigationController pushViewController:[[UIViewController alloc] init] animated:YES];

//方法二
/*
 * 参数一: UIViewController, 该参数不可以使用UITabBarController的实例
 * 参数二: 要求展示UIViewController的对象
 */
[navigationController showViewController:[[UIViewController alloc] init] sender:nil];

2.pop

//pop一个UIViewController
/*
 * 参数一: 是否执行动画
 * 返回值: 从UIViewController堆栈中Pop出来的UIViewController
 */
UIViewController *viewController = [navigationController popViewControllerAnimated:YES];

//一直pop到根视图控制器
/*
 * 参数一: 是否执行动画
 * 返回值: 从UIViewController堆栈中Pop出来的UIViewController数组
 */
NSArray *viewControllers = [navigationController popToRootViewControllerAnimated:YES];

//一直pop到指定的UIViewController
/*
 * 参数一: 指定UIViewController, 该UIViewController必须位于当前UIViewController堆栈中
 * 参数二: 是否执行动画
 * 返回值: 从UIViewController堆栈中Pop出来的UIViewController数组
 */
NSArray *viewControllers = [navigationController popToViewController:navigationController.viewControllers[0] animated:YES];

3.获取

// 获取位于UIViewController堆栈栈顶位置的UIViewController
UIViewController *viewController = navigationController.topViewController;

三.UINavigationBar的管理

UINavigationController通过位于UIViewController堆栈栈顶位置的UIViewControllernavigationItem属性(该属性位于UIViewControllerUINavigationControllerItem类目中)来管理UINavigationBar展示的内容,同时UINavigationController也提供了navigationBar属性, 允许开发者通过该属性设置UINavigationBar的外观。

值得注意的是,UINavigationControllerUINavigationBardelegate, 其负责响应该UINavigationBarDelegate的代理方法, 并据此更新位于界面中间部分的UIViewController的视图。

1.设置UINavigationBar的外观

我们可以通过该属性设置UINavigationBar的外观, 但是不要通过该属性设置其frame, bounds, alpha等属性, 更不要修改其层级结构。

// 属性
@property(nonatomic, readonly) UINavigationBar *navigationBar;
// 示例
navigationController.navigationBar.barStyle = UIBarStyleDefault;

2.设置UINavigationBar的隐藏状态

// 属性
@property(nonatomic, getter=isNavigationBarHidden) BOOL navigationBarHidden;
// 示例
navigationController.navigationBarHidden = YES;

3.设置UINavigationBar的隐藏状态(可选动画)

// 方法
/*
 * 参数一: 隐藏状态
 * 参数二: 是否执行动画
 */
- (void)setNavigationBarHidden:(BOOL)hidden animated:(BOOL)animated;
// 示例
[navigationController setNavigationBarHidden:YES animated:YES];

四.UIToolbar的管理

UINavigationController通过位于UIViewController堆栈栈顶位置的UIViewControllertoolbarItems属性(该属性位于UIViewControllerUINavigationControllerContextualToolbarItems类目中)来管理UIToolbar展示的内容,同时UINavigationController也提供了toolbar属性, 允许开发者通过该属性设置UIToolbar的外观。

1.设置UIToolbar的外观

// 属性
@property(nonatomic, readonly) UIToolbar *toolbar;
// 示例
navigationController.toolbar.barStyle = UIBarStyleDefault;

2.设置UIToolbar的隐藏状态

// 属性
@property(nonatomic, getter=isToolbarHidden) BOOL toolbarHidden;
// 示例
navigationController.toolbarHidden = NO;

3.设置UIToolbar的隐藏状态(可选动画)

// 方法
/*
 * 参数一: 隐藏状态
 * 参数二: 是否执行动画
 */
- (void)setToolbarHidden:(BOOL)hidden animated:(BOOL)animated;
// 示例
[navigationController setToolbarHidden:NO animated:YES];

五.手势识别器的管理

1.获取手势识别器

// 侧滑返回手势识别器
@property(nonatomic, readonly) UIGestureRecognizer *interactivePopGestureRecognizer;
// 用于轻拍隐藏UINavigationBar与UIToolbar的手势识别器
@property(nonatomic, readonly, assign) UITapGestureRecognizer *barHideOnTapGestureRecognizer;
// 用于轻扫隐藏UINavigationBar与UIToolbar的手势识别器
@property(nonatomic, readonly, strong) UIPanGestureRecognizer *barHideOnSwipeGestureRecognizer;
// 示例
UIGestureRecognizer *interactivePopGestureRecognizer = navigationController.interactivePopGestureRecognizer;

2.通过手势隐藏UINavigationBar与UIToolbar

// 轻拍隐藏、再次轻拍显示
@property(nonatomic, readwrite, assign) BOOL hidesBarsOnTap;
// 向上轻扫隐藏、向下轻扫显示
@property(nonatomic, readwrite, assign) BOOL hidesBarsOnSwipe;
// 横屏隐藏(此时轻拍显示)、竖屏显示
@property(nonatomic, readwrite, assign) BOOL hidesBarsWhenVerticallyCompact;
// 键盘出现隐藏、键盘消失保持隐藏(此时轻拍显示)
@property(nonatomic, readwrite, assign) BOOL hidesBarsWhenKeyboardAppears;
// 示例
navigationController.hidesBarsOnTap = YES;

六.UINavigationController对象的初始化

//通过UIViewController初始化
/*
 * 参数一: UIViewController, 该参数不可以使用UITabBarController的实例
 */
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:[[UIViewController alloc] init]];

//通过UINavigationBar、UIToolbar初始化
/*
 * 参数一: 自定义UINavigationBar的子类, 如果是nil则为UINavigationBar类
 * 参数二: 自定义UIToolbar的子类, 如果是nil则为UIToolbar类
 */
UINavigationController *navigationController = [[UINavigationController alloc] initWithNavigationBarClass:[UINavigationBar class] toolbarClass:[UIToolbar class]];

七. UINavigationBar

1.概述

UINavigationBar是一个在层级结构中起导航作用的视觉控件, 其一般展示形式如下图所示

2018-07-11 UINavigationController和UINavigationBar_第3张图片

2.UINavigationItem堆栈的管理

UINavigationBar虽然继承自UIView, 但是其并非通过addSubview:方法来添加子视图, 而是通过其管理的UINavigationItem堆栈来决定展示在UINavigationBar中的内容。

如下图所示,其中:
itemsUINavigationItem堆栈;
topItem是位于UINavigationItem堆栈栈顶位置的UINavigationItem;
backItem是位于UINavigationItem堆栈栈顶下方位置的UINavigationItem

2018-07-11 UINavigationController和UINavigationBar_第4张图片

我们可以利用系统提供的方法向UINavigationItem堆栈中Push一个UINavigationItem, 从UINavigationItem堆栈中Pop一个UINavigationItem, 也可以直接设置UINavigationItem堆栈中的全部UINavigationItem

3. UINavigationBar的内容

UINavigationBar通过UINavigationItem堆栈按照如下方式来决定展示在UINavigationBar中的内容

位于中间的标题会根据下方顺序选择展示的内容:

  • 如果topItem设置了标题视图(titleView属性), 则展示标题视图

  • 如果topItem设置了标题文字(title属性), 则展示标题文字

  • 如果以上都未设置, 则展示空白

位于右侧的按钮会根据下方顺序选择展示的内容:

  • 如果topItem设置了右侧按钮(rightBarButtonItem属性), 则展示右侧按钮

  • 如果以上都未设置, 则展示空白

位于左侧的按钮会根据下方顺序选择展示的内容:

  • 如果topItem设置了左侧按钮(leftBarButtonItem属性), 则展示左侧按钮

  • 如果backItem设置了返回按钮(backBarButtonItem属性), 则展示返回按钮

  • 如果backItem设置了标题文字(title属性), 则展示利用标题文字封装的返回按钮

  • 如果以上都未设置, 则展示利用文字"Back"封装的返回按钮(前提是UINavigationItem堆栈中有超过一个的UINavigationItem

// 初始化UINavigationItem对象
/*
 * 参数一: 标题文字
 */
- (instancetype)initWithTitle:(NSString *)title;
// 示例
UINavigationItem *navigationItem = [[UINavigationItem alloc] initWithTitle:@"Owen"];

//设置标题文字
// 属性
@property(nonatomic, copy) NSString *title;
// 示例
navigationItem.title = @"Title";

//设置标题视图
// 属性
@property(nonatomic, strong) UIView *titleView;
// 示例
navigationItem.titleView = [UIButton buttonWithType:UIButtonTypeInfoLight];

//设置提示文字
// 属性
@property(nonatomic, copy) NSString *prompt;
// 示例
navigationItem.title = @"Prompt";

//设置返回按钮
// 属性
@property(nonatomic, strong) UIBarButtonItem *backBarButtonItem;
// 示例
UIBarButtonItem *barButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Owen" style:UIBarButtonItemStylePlain target:nil action:nil];
navigationItem.backBarButtonItem = barButtonItem;

4.UINavigationBar的外观

UINavigationBar类中提供了大量属性/方法用于设置其外观, 我们可以设置其样式、背景颜色、色彩颜色、文字属性等

2018-07-11 UINavigationController和UINavigationBar_第5张图片

同样, 我们也可以设置其背景图片、阴影图片等

2018-07-11 UINavigationController和UINavigationBar_第6张图片
//设置样式
//该属性默认为UIBarStyleDefault(白底黑字), 可选项为UIBarStyleBlack(黑底白字)
navigationBar.barStyle = UIBarStyleDefault;

//设置透明性
navigationBar.translucent = YES;

//设置背景颜色
navigationBar.barTintColor = [UIColor orangeColor];

//设置色彩颜色
navigationBar.tintColor = [UIColor greenColor];

//设置标题文字属性
navigationBar.titleTextAttributes = @{NSFontAttributeName: [UIFont systemFontOfSize:30], NSForegroundColorAttributeName: [UIColor whiteColor]};

//设置/获取背景图片
/*
 * 参数一: 背景图片
 * 参数二: 默认为UIBarPositionAny(不指定), 可选项为UIBarPositionBottom(在容器下方), UIBarPositionTop(在容器上方), UIBarPositionTopAttached(在屏幕上方, 与容器平级)
 * 参数三: 可选项为UIBarMetricsDefault(竖屏, 横屏未设置也使用该效果), UIBarMetricsCompact(横屏), UIBarMetricsDefaultPrompt(拥有提示文字的竖屏, 横屏未设置也使用该效果), UIBarMetricsCompactPrompt(拥有提示文字的横屏)
 */
[navigationBar setBackgroundImage:[UIImage imageNamed:@""] forBarPosition:UIBarPositionTop barMetrics:UIBarMetricsDefault];

//设置阴影图片
navigationBar.shadowImage = [UIImage imageNamed:@""];

//设置返回按钮图片(需要同时设置)
navigationBar.backIndicatorImage = [UIImage imageNamed:@""];
navigationBar.backIndicatorTransitionMaskImage = [UIImage imageNamed:@""];

你可能感兴趣的:(2018-07-11 UINavigationController和UINavigationBar)