Skip to content

Latest commit

 

History

History
194 lines (141 loc) · 7.76 KB

16.UI基础之UINavigationController.md

File metadata and controls

194 lines (141 loc) · 7.76 KB

16.UI基础之UINavigationController

导航控制器并非视图控制器,视图控制器用来综合管理当前界面中的视图,导航控制器则是一种框架结构,其内部管理的不是视图,而是视图控制器,可以将导航控制器理解为视图控制器的管理者。类似Android中Activity栈。

UINavigationController导航控制器用于显示多屏并且具有一定层次结构的内容,它维护了一个试图控制器栈,所有的子视图都处于栈内。与UITabBarController在切入和切出多个内容页面时类似,主要的区别就在于UINavigationController是用栈来实现的,更适合用于处理和显示分层的数据。

FirstViewController

在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

在SecondViewController中,导航栏控制器会默认生成一个leftBarButton返回按钮。

import UIKit

class SecondViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        title = "Second Page"
        view.backgroundColor = UIColor.green
    }
}

AppDelegate中设置导航栏控制器

在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