闲谈

最近做项目涉及到一个UINavigation​bar 的设置,网上给出的方法大多都很不全面,于是乎决定看 API 来研究一下 UINavigationController。至于我遇到的问题在本篇文章中会写到。

认识 UINavigationController

官方 API 给的解释是: The UINavigation​Controller class implements a specialized view controller that manages the navigation of hierarchical content. This navigation interface makes it possible to present your data efficiently and makes it easier for the user to navigate that content. You generally use this class as-is but you may also subclass to customize the class behavior. 理解起来也很简单: UINavigationController 类实现了管理分层内容导航的专用视图控制器,该导航界面可以有效地呈现数据,并且可以使用户更容易浏览该内容。 通常可以直接在使用,也可以使用子类自定义。

管理方式:

UINavigationController通过栈的方式管理控制器的切换,控制入栈和出栈来展示各个视图控制器。栈中的第一个视图控制器是根视图控制器。最后一个视图控制器是当前正在显示的视图控制器。 整个过程就像是向弹夹里压子弹,弹夹就可以看成是一个栈,子弹就是每一个被管理的试图控制器。不停地向弹夹里压子弹,最后一个压进去的就会在最上边,我们看到的就是最上边那个,也就是说我们看到的视图永远是栈顶的那个。

navigationController 管理位于界面顶部的 navigation bar和位于界面底部的一个可选的 toolbar。很多人知道 navigation bar 但是不知道 toolbar。 navigation bar始终显示,并且是由 navigation controller 自身来管理的,并且可以根据栈中的视图控制器来更新它的内容(像 UINavigationBar 的一下属性)。 toolbar 的显示是依据于属性isToolbarHidden的。该属性的默认值是 true。所以一般来说我们使用 UINavigationController的时候是看不到他的。当这个属性值为 false 的时候,navigation controller也是根据栈顶的viewController的内容来更新他的。

初始化方法

UINavigationController 两种初始化方法:

  @available(iOS 5.0, *)public init(navigationBarClass: Swift.AnyClass?, toolbarClass: Swift.AnyClass?)public init(rootViewController: UIViewController)
复制代码

首先第二种就不做解释了,如果不会,那么你该去面壁了。 ~***但是要提出的一点是rootViewController不能是 UITab​Bar​Controller 的实例。***~ 那么让我们来看第一种吧,第一种初始化方法有两个参数,这两个参数要求都是:AnyClass。但是官方 API 对参数的要求是: navigation​Bar​Class 指定要使用的自定义UINavigationBar子类,或指定使用标准UINavigationBar类的nil。 toolbar​Class 指定要使用的自定义UIToolbar子类,或指定使用标准UIToolbar类的nil。

下面给出一种实现方法:(代码) 1.自定义 UINavigationBar的子类

class YHYNavigationBar: UINavigationBar {override init(frame: CGRect) {super.init(frame: frame)// 你可以在上边加一个 UIView 的子类let image = UIImageView(frame: CGRect(x: 8, y: 5, width: 22, height: 22))self.addSubview(image)image.image = UIImage(named: "arrow_44")}required init?(coder aDecoder: NSCoder) {super.init(coder: aDecoder)}override func draw(_ rect: CGRect) {// 你可以用 UIBezierPath 画一个图形let bezier = UIBezierPath()bezier.move(to: CGPoint(x: 0, y: 0))bezier.addLine(to: CGPoint(x: 0, y: 32))bezier.addQuadCurve(to: CGPoint(x:UIScreen.main.bounds.width,y:32), controlPoint: CGPoint(x: UIScreen.main.bounds.width / 2, y: 56))bezier.addLine(to: CGPoint(x: UIScreen.main.bounds.width, y: 32))bezier.addLine(to: CGPoint(x: UIScreen.main.bounds.width, y: 0))UIColor.yellow.setFill()bezier.fill()}
}
复制代码
  1. 定义一个UIToolbar子类
class YHYToolbar: UIToolbar {override init(frame: CGRect) {super.init(frame: frame)self.barTintColor = UIColor.whiteself.isTranslucent = falseself.setBackgroundImage(UIImage(), forToolbarPosition: .any, barMetrics: .default)self.setShadowImage(UIImage(), forToolbarPosition: .any)let image = UIImageView(frame: CGRect(x: 20, y: 8, width: 28, height: 28))self.addSubview(image)image.image = UIImage(named: "arrow_44")}required init?(coder aDecoder: NSCoder) {super.init(coder: aDecoder)}}
复制代码

结果的样子:

写到这里是不是有很多小伙伴就准备用这个方法来自定义自己想要的导航栏了呢? 其实这算是一种方法,但是官方 API 并不支持使用这一种方法,而是推荐使用的方法是这样的。 官方 API 给出的建议是 To customize the overall appearance of a navigation bar, use UIAppearance APIs instead of this method. If you use this initialization method to create a navigation bar that uses custom bar subclasses, you are responsible for pushing and setting view controllers before presenting the navigation controller onscreen. 大概意思是: 要定制导航栏的整体外观,请使用UIAppearance API而不是此方法。 如果您使用此初始化方法创建使用自定义栏子类的导航栏,则在将屏幕上显示导航控制器之前,您有责任推送和设置视图控制器。 具体使用可以看这里,下面我们给出一些关于UINavigationBar使用UIAppearance的示例: (更全面的你可以看这里)

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {// UINavigationBar的填充颜色UINavigationBar.appearance().barTintColor = UIColor.brown// UINavigationBar 的 title 的字体颜色,字体大小,是一个字典类型的赋值,更多属性,你可以 command+鼠标左键 字典中的任何一个键值去看UINavigationBar.appearance().titleTextAttributes = [NSFontAttributeName : UIFont.systemFont(ofSize: 24), NSForegroundColorAttributeName: UIColor.white]// UINavigationBar 的背景图片 注意:这个设置之后 barTintColor 就会失效,原因也很简单,都是用来做背景的//   UINavigationBar.appearance().setBackgroundImage(UIImage(), for: .default)//  这个关系到 UINavigationBar底部的那条黑线//  UINavigationBar.appearance().shadowImage = UIImage()return true}复制代码

访问Navigation Stack中的元素

此时大家都知道UINavigationController通过栈的方式来管理视图控制器的,那么怎么访问栈中存在的视图控制器呢?

// UINavigationController的一个属性 ,可以访问到栈顶端的那个试图控制器,一般是正在显示的那个open var topViewController: UIViewController? { get } open var visibleViewController: UIViewController? { get } // UINavigationController的一个属性 ,栈中所有的试图控制器,你可以打印一下看出当前      UINavigationController管理了多少个试图控制器open var viewControllers: [UIViewController] @available(iOS 3.0, *)open func setViewControllers(_ viewControllers: [UIViewController], animated: Bool)
复制代码

视图的切换方法

视图控制器的切换也是一个重要的部分,这些方法也都很常见,很简单,只做部分注释,不做代码演示了。

// 向栈中推进一个 viewController 用于显示出这个试图控制器open func pushViewController(_ viewController: UIViewController, animated: Bool) // 推出栈顶的那个 viewController,返回到之前的页面  open func popViewController(animated: Bool) -> UIViewController? // 退回到指定的试图控制器,这下之前的viewControllers属性就有用处了,你可以根据viewControllers中的视图控制器 指定退回到哪一个open func popToViewController(_ viewController: UIViewController, animated: Bool) -> [UIViewController]? // 直接将栈中除了最底端的根视图控制器之外的所有试图控制器推出,从而显示根试图控制器,也就是最早进入栈中的试图控制器open func popToRootViewController(animated: Bool) -> [UIViewController]?
复制代码

隐藏导航栏

UINavigationController 提供了几种属性来分别对待不同情况下对NavigationBar的隐藏,都比较简单:

      //  隐藏UINavigationBar//  self.navigationController?.isNavigationBarHidden = true//  self.navigationController?.hidesBarsWhenVerticallyCompact = true//  键盘弹出时隐藏UINavigationBar//   self.navigationController?.hidesBarsWhenKeyboardAppears = true//  轻拍手势隐藏UINavigationBar//  self.navigationController?.hidesBarsOnTap = true//  根据滑动手势来隐藏其导航条//    self.navigationController?.hidesBarsOnSwipe = true复制代码

UINavigation​Controller​Delegate

使用导航控制器的delegate(实现此协议的自定义对象)来修改从UINavigation Controller对象的导航堆栈中推送或弹出视图控制器时的行为。

public protocol UINavigationControllerDelegate : NSObjectProtocol {// 比较常用的是这两个,看到就很容易理解也就不多讲了@available(iOS 2.0, *)optional public func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool)@available(iOS 2.0, *)optional public func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool)}
复制代码

到这里 UINavigationController 的使用才仅仅是冰山一角,最重要的角色还在幕后,是谁呢?自然是UINavigationBar,主角的光辉需要一个独立的舞台尽情发挥。那么!

UINavigationBar请看下一集,精彩不可错过!

其实UINavigationController还有一些转场动画的实现,因为目前所探讨的都是一些基础属性的使用,所以转场动画会在以后分享出来!

UINavigation​Controller 的详解(基于 API )相关推荐

  1. php 六边形 属性图 能力数值图,详解基于 Canvas 手撸一个六边形能力图

    一.前言 六边形能力图如下,由 6 个 六边形组成,每一个顶点代表其在某一方面的能力.这篇文章我们就来看看如何基于 canvas 去绘制这么一个六边形能力图.当然,你也可以基于其他开源的 js 方案来 ...

  2. k8s学习笔记(10)--- kubernetes核心组件之controller manager详解

    kubernetes核心组件之controller manager详解 一.Controller Manager简介 1.1 Replication Controller 1.2 Node Contr ...

  3. k8s、ServiceAccount权限详解、RBAC 详解(基于角色的访问控制),常用操作指令

    文章目录 Service Account应用示例 RBAC 详解(基于角色的访问控制) 创建一个角色(role)---权限 实验二 常用操作指令 Service Account应用示例 概念图权限关系 ...

  4. Elastic search入门到集群实战操作详解(原生API操作、springboot整合操作)-step1

    Elastic search入门到集群实战操作详解(原生API操作.springboot整合操作)-step2 https://blog.csdn.net/qq_45441466/article/de ...

  5. mysql cluster rpm包的作用_MySQL之——MySQL Cluster集群搭建详解(基于RPM安装包)

    1.下载MySQL-cluster 7.3.7 http://dev.mysql.com/downloads/cluster/ 2.环境清理及安装 1)清理CentOS6.5自带的mysql服务,其中 ...

  6. 详解基于 Cortex-M3 的任务调度(下)

    文章目录 工程说明 实验结果 代码讲解 时钟节拍 任务切换 task_switch() PendSV_Handler 任务的代码 重要的全局变量 main() 函数 代码下载 在 详解基于 Corte ...

  7. 《嵌入式Linux软硬件开发详解——基于S5PV210处理器》——2.2 DDR2 SDRAM芯片

    本节书摘来自异步社区<嵌入式Linux软硬件开发详解--基于S5PV210处理器>一书中的第2章,第2.2节,作者 刘龙,更多章节内容可以访问云栖社区"异步社区"公众号 ...

  8. java spring mvc 上传_Java Spring MVC 上传下载文件配置及controller方法详解

    下载: 1.在spring-mvc中配置(用于100M以下的文件下载) 下载文件代码 @RequestMapping("/file/{name.rp}") public Respo ...

  9. python selenium爬虫_详解基于python +Selenium的爬虫

    详解基于python +Selenium的爬虫 一.背景 1. Selenium Selenium 是一个用于web应用程序自动化测试的工具,直接运行在浏览器当中,支持chrome.firefox等主 ...

最新文章

  1. 02面向对象设计原则
  2. linux conntrack命令 路由连接 跟踪表 显示删除监听记录
  3. php循环给数组每个值加引号,php数组非数字键名加引号的必要性!
  4. java enum 变量_java枚举使用详解
  5. 2018 上海.NET职位围观报告
  6. 枚举算法:最小连续n个合数。试求出最小的连续n个合数(其中n是键盘输入的任意正整数)。
  7. 想看程序员的成长课这本书
  8. LeetCode——75. 颜色分类(面试题)
  9. PPC2003SE开发日记-资源之工具安装(JONSON原创)
  10. 高精度ua级恒流源_一种高精度可调恒流源电路的制作方法
  11. 游园惊梦之“想做学者么?”有感
  12. 电脑没有使用计算机进入睡眠状态,电脑打不开,屏上显示:无视频输入,进入睡眠模式。怎么处理...
  13. 短信发送显示服务器失败,手机短信发不出去怎么办 手机故障解决方法【方法步骤】...
  14. 精简配置的虚拟磁盘在快照删除过程中膨胀为更大的大小(56608)
  15. 认知计算框架有哪些?
  16. branch什么意思中文翻译_给宝宝读英文绘本,到底要不要中文翻译?
  17. 【深度学习系列】数据预处理
  18. 计算机收藏夹位于哪个磁盘,win10收藏夹在电脑什么位置_win10系统收藏夹在哪里...
  19. linux分区sda和sdb合并,给系统新添加硬盘sdb后,怎么分配给sda下某个分区
  20. Python篇之编译py文件为pyc文件的方法总结

热门文章

  1. NET4.0新功能之String.IsNullOrWhiteSpace() 方法
  2. 代码中一些经常使用的小技巧
  3. require.js的AMD规范详解
  4. STL 源代码分析 算法 stl_algo.h -- includes
  5. 项目中js文件修改后浏览器不能及时更新的解决办法
  6. Checkbox与RadioGroup的使用方法
  7. TRACERT命令及用法
  8. 9-15 redis-trib构建集群
  9. 客户端压测server端计算qps以及不同延迟时间下响应数量所占百分比
  10. treeset可以重复吗_java容器(五)HashSet与TreeSet