导航控制器并非视图控制器,视图控制器用来综合管理当前界面中的视图,导航控制器则是一种框架结构,其内部管理的不是视图,而是视图控制器,可以将导航控制器理解为视图控制器的管理者。类似Android中Activity栈。
UINavigationController导航控制器用于显示多屏并且具有一定层次结构的内容,它维护了一个试图控制器栈,所有的子视图都处于栈内。与UITabBarController在切入和切出多个内容页面时类似,主要的区别就在于UINavigationController是用栈来实现的,更适合用于处理和显示分层的数据。
在FirstViewController中,我们设置了title和背景颜色,title是这个视图控制器的标题,如果有导航条的话,这个title会显示在导航条的中心位置,如果没有导航条的话,它就没什么作用
import UIKit
class FirstViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
title = "First Page"
view.backgroundColor = UIColor.red
// 创建一个UIBarButtonItem,并替换了默认的导航条右侧按钮
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "下一页",
style: .plain, target: self, action: #selector(startNext))
// navigationItem.leftBarButtonItem设置左边的按钮
}
@objc func startNext() {
// 跳转到下一个页面
navigationController?.pushViewController(SecondViewController(), animated: true)
}
}
在SecondViewController中,导航栏控制器会默认生成一个leftBarButton返回按钮。
import UIKit
class SecondViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
title = "Second Page"
view.backgroundColor = UIColor.green
}
}
在AppDelegate.swift中,将FirstViewController设置为导航控制器的跟视图控制器。
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// 将FirstViewController设置为rootview的导航控制器
window?.rootViewController = UINavigationController(rootViewController: FirstViewController())
return true
}
}
上面就是一个简单的导航控制器,它有一个根视图控制器,当点击rightBarButtonItem时,SecondViewController会被push到导航控制器中。
- push相当于入栈操作
- pop相当于出栈操作
- 根据堆栈先进先出的规则,当执行pop操作时,位于栈顶的试图控制器将被从导航控制器中移除
假设我们想在SecondViewController中隐藏导航栏
class SecondViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
title = "Second Page"
view.backgroundColor = UIColor.green
}
override func viewWillAppear(_ animated: Bool) {
navigationController?.setNavigationBarHidden(true, animated: false)
}
}
在平时开发过程中经常会用到UINavigationController和UITabBarController配合使用的情况,例如上一节中我们说到的微信的例子,可以在AppDelegate.swift中进行如下修改
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let wechat = WeChatViewController()
// 未选中状态Tab图片
wechat.tabBarItem.image = UIImage(named: "tab1")?.withRenderingMode(.alwaysOriginal)
// 选中状态Tab图片
wechat.tabBarItem.selectedImage = UIImage(named: "selectTab1")?.withRenderingMode(.alwaysOriginal)
// Tab的文本
wechat.tabBarItem.title = "微信"
// 未读消息角标
wechat.tabBarItem.badgeValue = "10"
let addressBook = ContactViewController()
addressBook.tabBarItem.image = UIImage(named: "tab2")?.withRenderingMode(.alwaysOriginal)
addressBook.tabBarItem.selectedImage = UIImage(named: "selectTab2")?.withRenderingMode(.alwaysOriginal)
addressBook.tabBarItem.title = "通讯录"
let find = FindViewController()
find.tabBarItem.image = UIImage(named: "tab3")?.withRenderingMode(.alwaysOriginal)
find.tabBarItem.selectedImage = UIImage(named: "selectTab3")?.withRenderingMode(.alwaysOriginal)
find.tabBarItem.title = "发现"
let mine = MineViewController()
mine.tabBarItem.image = UIImage(named: "tab4")?.withRenderingMode(.alwaysOriginal)
find.tabBarItem.selectedImage = UIImage(named: "selectTab4")?.withRenderingMode(.alwaysOriginal)
mine.tabBarItem.title = "我的"
let tabBarController = UITabBarController()
// tabBarController的主题颜色
tabBarController.tabBar.tintColor = UIColor.white
// **************新增部分,把上面的四个Controller都用NavigationControoler封装
wechat.title = "微信"
let wechatNavigationController = UINavigationController(rootViewController: wechat)
addressBook.title = "通讯录"
let addressBookNavigationController = UINavigationController(rootViewController: addressBook)
find.title = "发现"
let findNavigationController = UINavigationController(rootViewController: find)
mine.title = "我的"
let mineNavigationController = UINavigationController(rootViewController: mine)
// tabBarController.viewControllers = [wechat,addressBook,find,mine]
// 然后将viewControllers全部修改为NavigationController
tabBarController.viewControllers = [wechatNavigationController, addressBookNavigationController, findNavigationController, mineNavigationController]
// *****************修改结束
tabBarController.selectedIndex = 2
// 添加到rootViewController
window?.rootViewController = tabBarController
return true
}
可以看到每个页面都有导航栏了。
// 跳转到下一个控制器
navigationController?.pushViewController(SecondViewController(), animated: true)
// 返回到上一个控制器
navigationController?.popViewController(FirstViewController(), animated: true)
// 返回到根导航控制器
navigationController?.popToRootViewController(animated: true)
// 当前导航栈里所有的控制器
let navis = navigationController?.viewControllers
// 获取当前显示的控制器
navigationController?.visibleViewController
// 设置是否滑动屏幕的左边能够返回
navigationController?.interactivePopGestureRecognizer?.delegate = self
- 邮箱 :charon.chui@gmail.com
- Good Luck!