更新:2018.05.24
整理了一下demo:SwiftDemo
-
UINavigationController
导航条控制器用于显示多屏并具有一定层次结构的内容,是构建分层应用的主要工具。 - 它维护了一个视图控制器栈,所有的子视图控制器都处于堆栈中。
-
UINavigationController
导航条控制器在管理、切入和切出多个内容页方面,与UITabBarController
类似。 -
UINavigaitonController
和UITabBarController
区别在于:UINavigationController
是作为栈来实现的,它更适合用于处理和显示分层的数据。
一、创建一个UINavigationController
- 首先我们还是新建一个项目,然后添加两个新的视图控制器:
FirstViewController
和SecondViewController
。
- 为了更好的演示,我们分别设置一下两个视图控制器的属性
FirstViewController.swift
import UIKit
class FirstViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
title = "第一页"
view.backgroundColor = UIColor.gray
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "下一页", style: .plain, target: self, action: #selector(nextPageClick))
}
func nextPageClick() {
navigationController?.pushViewController(SecondViewController(), animated: true)
}
}
SecondViewController
import UIKit
class SecondViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
title = "第二页"
view.backgroundColor = UIColor.cyan
}
}
a. 在FirstViewController
中,我们设置了title
和背景颜色,title
是这个视图控制器的标题,如果有导航条的话,这个title
会显示在导航条的中心位置,如果没有导航条的话,它就没什么作用,
b. 接着,我们创建了一个导航条右侧的按钮,确切的说,是重建了一个UIBarButtonItem
,并替换了默认的导航条右侧按钮。添加方法,点击这个按钮,调起nextPageClick ()
方法。
c. 当点击rightBarButtonItem
时,执行nextPageClick()
,然后当前视图控制器的导航控制器(navigationController)
调起pushViewController()
方法,目的是跳转到下一个视图控制器。pushViewController()
有两个参数,第一个参数表示需要加载的视图控制器,第二个参数表示是否需要动画效果。当然,这个方法只有在视图控制器的导航控制器被实例化之后才有效。
d. 在SecondViewController.swift
中,我们只设置了title
和背景颜色,当我们跳转到这个视图控制器,导航控制器会默认生成一个leftBarButton
返回按钮。
- 接下来,我们到
AppDelegate.swift
中,将FirstViewController
设置为导航控制器的跟视图控制器:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
window?.rootViewController = UINavigationController(rootViewController: FirstViewController())
return true
}
二、UINavigationController视图入栈和出栈
在上面我们创建了一个简单的导航控制器,这个导航控制器有一个根视图控制器,当点击rightBarButtonItem
时,SecondViewController
会被push到导航控制器中。
- 这里的push就相当于入栈操作。
- 与之相反的pop操作,相当于出栈。
- 根据堆栈的先进先出规则,当执行pop操作时,位于栈顶的视图控制器,将被从导航控制器的堆栈中移除。
这里就不实际举例说明了,比较好理解。
导航栏的显示和隐藏
我们可以在viewWillAppear()
中设置视图控制器的navigationController
的navigationBarHidden
属性来设置导航栏的隐藏和显示。
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.setNavigationBarHidden(true, animated: false)
}
a. navigationBarHidden ()
方法有两个参数,第一个参数表示是否隐藏导航栏,第二个属性表示是否需要动画效果。
三、导航栏样式
根据项目的需求,原始的导航栏很难满足我们的需求。
// 添加导航条上方的提示,这个属性被设置后,导航栏的高度将增加到74
navigationItem.prompt = "正在使用您的位置..."
// 设置导航栏不透明
navigationController?.navigationBar.isTranslucent = false
// 设置导航条样式
navigationController?.navigationBar.barStyle = UIBarStyle.black
// 设置导航栏关键元素颜色,tintColor属性是View专门用来指定所包含的关键元素的颜色
navigationController?.navigationBar.tintColor = UIColor.white
// 设置导航栏背景图片
navigationController?.navigationBar.setBackgroundImage(UIImage(named:""), for: .any, barMetrics: .default)
// 设置导航栏 title 的 Font
navigationController?.navigationBar.titleTextAttributes = [NSFontAttributeName:UIFont.boldSystemFont(ofSize: 18)]
// 设置导航栏 title 的 Color
navigationController?.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName:UIColor.white]
// 设置导航栏阴影部分图片,也就是导航栏下面那条细线
navigationController?.navigationBar.shadowImage = UIImage(named:"")
// 设置导航栏阴影颜色
navigationController?.navigationBar.layer.shadowColor = UIColor.green.cgColor
// 设置导航栏阴影偏移
navigationController?.navigationBar.layer.shadowOffset = CGSize(width: 0, height: 10)
// 设置导航栏阴影透明度
navigationController?.navigationBar.layer.shadowOpacity = 0.2
- 设置prompt属性之后,导航栏的高度会增加到74,并在导航栏的上方显示内容。
- translucent属性默认是 true ,当设置了该属性后,导航栏变成不透明,同时,视图控制器的view的高度也将发生变化。
- 导航栏也可以设置背景图片,通过setBackgroundImage()方法,该方法有三个参数,第一个参数代表图片,第二个参数和第三个参数都是枚举,第二个参数表示导航栏的位置,第三个参数表示导航栏的外观。具体可以自己试一下。
- titleTextAttributes属性是一个字典,一般我们用于设置导航栏标题的文本大小和字体。
- 导航栏的阴影部分是可以设置的,包括更改阴影部分的颜色、背景、大小等。
四、导航控制器和标签控制器
在iOS开发过程中,经常会将navigationCongtroller
和tabBarController
相结合使用,我们可以回到Swift(十三)UITabBarController的仿微信的例子,来看一下。
直接在AppDelegate.swift
文件中修改即可。
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
let wechat = WeChatViewController()
// 未选中状态Tab图片
wechat.tabBarItem.image = UIImage(named: "tab1")?.withRenderingMode(.alwaysOriginal)
// 选中状态Tab图片
wechat.tabBarItem.selectedImage = UIImage(named: "selectTab1")?.withRenderingMode(.alwaysOriginal)
let addressBook = AddressBookViewController()
addressBook.tabBarItem.image = UIImage(named: "tab2")?.withRenderingMode(.alwaysOriginal)
addressBook.tabBarItem.selectedImage = UIImage(named: "selectTab2")?.withRenderingMode(.alwaysOriginal)
let find = FindViewController()
find.tabBarItem.image = UIImage(named: "tab3")?.withRenderingMode(.alwaysOriginal)
find.tabBarItem.selectedImage = UIImage(named: "selectTab3")?.withRenderingMode(.alwaysOriginal)
let mine = MineViewController()
mine.tabBarItem.image = UIImage(named: "tab4")?.withRenderingMode(.alwaysOriginal)
mine.tabBarItem.selectedImage = UIImage(named: "selectTab4")?.withRenderingMode(.alwaysOriginal)
let tabBarController = UITabBarController()
tabBarController.tabBar.tintColor = UIColor.init(colorLiteralRed: 9/255.0, green: 187/255.0, blue: 7/255.0, alpha: 1)
wechat.title = "微信"
let wechatNavigationController = UINavigationController(rootViewController: wechat)
addressBook.title = "通讯录"
let addressBookNavigationController = UINavigationController(rootViewController: addressBook)
find.title = "发现"
let findNavigaitonController = UINavigationController(rootViewController: find)
mine.title = "我的"
let mineNavigationController = UINavigationController(rootViewController: mine)
tabBarController.viewControllers = [wechatNavigationController,addressBookNavigationController,findNavigaitonController,mineNavigationController]
window?.rootViewController = tabBarController
return true
}
a. 我们可以看到,现在TabBar的viewControllers
里面添加的都是UINavigationController
了。