IOS开发入门(11)-导航控制器I:层级结构和标签

前言:(直接从书上抄的)

  大多数应用程序是由主视图导出多个屏幕,并且通常情况下实现屏幕切换的方法还不止一种。我们需要一种方式来实现用户在应用程序内来回移动,以及让用户知道他们所在的具体部分提供的功能之间的切换。

  在iPhone设备上,大多数使用导航控制器的应用程序可以分为两种。一种使用简单的主视图来导航一系列展示或多或少、渐进的细节场景。通讯录、笔记和设置就是不错的示例。其他的,比如闹钟和音乐,则有许多主视图,各自拥有不同的功能,设置拥有自己的内容层次。

  iOS提供控制器来管理每种内容之间的导航。UINavigationController用于在各种层次结构的信息之间上下移动,而UITabBarController则处理多个主视图之间的切换。

  本节就是介绍这两种方法怎么使用。

1 导航控制器

  我们来看一下设置是长啥样的吧,下图展示的是setting方法应用程序中的某个局部的层级结构

  在iPhone上,这是常见的组织内容的方式。该方式优雅地解决了如何在狭小空间内显示大量内容的问题。setting允许修改iPhone和setting内部各种应用程序的数以百计的设置选项。采用层次结构的方式来“折叠”内容,能够很好地应用两种屏幕尺寸,以及很好地复合人们通常善于分类和分组的情况。

  那些拥有带层次结构的内容的应用程序,工作方式一般基本相同。在屏幕层级的顶部,会有内容概述,然后就是多个带更多细节的屏幕。setting应用程序就是不错的示例。在顶层,一开始是setting应用的所有相关的分类,然后是能够持续向下深入,直到到达特定设置的细节。

  UINavigationController正是为了处理这种类型的导航而设。他跟踪客户,就像它位于导航中不同屏幕的层次结构,并提供默认的控件返回。该控制器通过将所有内容都嵌入它内部来实现这一点。

  上图显示了导航控制器的一部分。顶部是导航栏。导航栏通常会用在上下文中或展开的当前路径。标题通常为用户正在观看的内容。正如我们很快就会看到的一样,在导航路径中,左手边的后退按钮能够让用户返回上一节。在导航栏上,用户可以自定义按钮

  位于底部的是一个可选的工具栏,是另一处让我们设置空间的地方,上面放了一个操作按钮。我们的视图控制器位于灰色地带。而在当前场景的某个地方,需要提供一个方法来打开下一级详细页面。例如,在Add/View场景中的Edit按钮

  当使用导航控制器时,一开始可以将它连接到第一个场景或根场景(一个视图控制器)。当导航控制器打开时,他就会打开根场景。正如我们将其关联到一个新的场景(视图控制器),导航控制器会将它放在当前路径上,并显示该场景。

  在视图控制器的堆栈中,根视图位于底部,路径通常也会被记录。

介绍一下导航控制类

  所有的导航功能都通过5个主要类来提供:

  • UINavigationController为当前导航堆栈协调所有的组件。除了管理导航堆栈和所有砖厂(transition)之外,它有指向导航栏和可选工具栏的引用
  • UINavigationBar是位于屏幕顶部的导航栏视图。UINavigationController用它显示当前场景的标题和一个按钮,如果需要的话,它可以用于返回前一个界面。它可以独立地使用,但是不推荐这样做
  • UINavigationItem管理层次结构中某个特定视图控制器的UINavigationBar。它有如下各项的属性:设置标题,显示、添加和隐藏工具栏按钮,包括Back按钮
  • UIBarButtonItem提供了一个对象来管理导航和工具栏上的按钮。从系统提供按钮(如Done(完成)、Cancel(取消)和到文本按钮的操作(action)等),可以创建出任意按钮。Button Item既不是UIButton,也不是视图(View)类型。它们是管理项,可以显示用户界面中的东西。可以将UIButton放在Button Item(按钮项)里面
  • UIToolbar管理一个可选的工具栏,通常位于屏幕的底部。其拥有方法与属性来设置Button Item(按钮项)和外观,以及一种方式来指定其位置是在屏幕的顶部还是底部

      UINavigationItem使用当前视图控制器的title属性来设置文本。更改title会改变文本。之前在本地化的场景标题我们见过这个操作。

      下图显示了在CarValet应用程序的Add/View场景中与导航控制器相关的对象

  导航控制器管理Add/View场景以及其他场景。每个被管理的场景有一个UINavigationItem,用于设置导航栏的内容以及标题。Add/View场景的标题栏也有一个工具栏按钮,以显示car images场景。

  观看上图的圈圈,这是一个特殊的关联标识符(segue identifier),是为第一个控制器或根视图控制器而设。不想push segue,着开起来想一条两端都有一个圆的线。根场景是导航控制器展示的第一个场景。故事版中的另一个链接显示了场景之间的导航路径。例如在Add/View于Edit场景之间存在一个链接。因为无处可去只有返回,Edit场景就是一个叶节点,如同第一张图的叶节点。

添加工具栏

  (从书上抄了那么多字真是类,觉得还是介绍一下比较好),现在开始干正事。

  首先我们要把图标添加到项目的资产库中。我们需要图标,可以
在这里下载,但是那需要自己找;也可以在这里我的github下载。最好是从我的github上下载吧。

  好了,图标下载完了,要添加到资产库中,如下图操作方式

  选+之后,会跳出一个目录,到最下面找到Import,点完import,选中要导入的文件就行啦

  • 现在图标加进去了,我们要加底部工具栏了,打开故事面板

  • 添加完工具栏,放置按钮

  • 选择左边的按钮,Image设置为sign_out;右边那个按钮,Image设置为sign_in;中间的按钮,title改为Edit。

  • 删除原来的Previous、Next和Edit按钮,

  • 将我们之前添加的左右箭头通过下图方法设置关联,左箭头选择previousCar,右箭头选择nextCar

  • 当我们删除Edit按钮时,也删除了到Edit场景的关联(segue),我们要将它恢复,将它拉到Edit场景,选择push,并设置标识符为Editsegue,与之前的Edit按钮所用的关联名称一样

      然后运行程序你可能会发现下面的导航栏没有出现,那么在ViewController.m中的viewDidLoad方法中,添加self.navigationController.toolbarHidden = NO;使他正好位于[super viewDidLoad];下面,这时候就出现了,但是点开其他的例如car images,下面也出现了导航栏,这显然不是我们想要的,在Edit等场景里面也是这个情况。可以在他们各自的viewDidLoad方法中添加self.navigationController.toolbarHidden = YES;,这样就默认为隐藏了。然而还有个问题,当我们从其他场景退出返回到Add/View场景时,导航栏消失了,他也是被隐藏了,那我们就换个地方,在ViewController.m中的viewWillAppear方法中,添加self.navigationController.toolbarHidden = NO;,这样每次加载的时候,就自动设置回去了。这样就设置完成啦。

(PS,颜色是我后来弄的,到这步按钮颜色应该是蓝色的,导航栏应该是白色的,而且没有About)

基于消息的导航

到目前为止,我们已经使用segue在场景之间进行导航,包括使用特使的exit segue。我们拥有一些控制器可以传递数据并能使用prepareForSegue:方法修改行为。借助于UINavigationController的属性和消息,可以拥有完全控制权。可以实现如下类似行为:将新的视图控制器推给堆栈(push),弹出(pop)当前视图控制器,弹出根视图控制器之上的所有控制器,获取当前导航堆栈中的控制器数组,甚至重新排列视图控制器数组。

可以使用基于代码的消息,为CarValet应用程序添加一个About场景,而不是在故事面板中添加,而是可以在单独的用户界面资源文件中创建界面。在Xcode中,这些文件是XIB文件

实现步骤如下:

  • 创建一个新的Cocoa Touch Class,命名为AboutViewController,并选中“Also create XIB file”
  • 这时候多出了三个文件,将他们放到supporting files的上面
  • 打开AboutViewController.xib,这是IB文件,不支持任何脚本功能,如segue何连接。使用Attributes检查器将视图的顶部栏设置为不透明的导航栏,发现导航栏不能编辑

  • 使用Lable或其他,自行添加内容
  • 打开故事面板,添加一个About按钮。位置看上面的图。
  • 在ViewController.m中import AboutViewController.h
  • 将About拉到ViewController.h中创建action,名称为aboutCarValet
  • aboutCarValet方法代码如下:
- (IBAction)aboutCarValet:(id)sender {AboutViewController *nextController;nextController = [[AboutViewController alloc]initWithNibName:@"AboutViewController"//1bundle:[NSBundle mainBundle]];nextController.title = @"About CarValet";//2[self.navigationController pushViewController:nextController animated:YES];
}

注释:

  1. 为AboutViewController实例初始化next Controller视图控制器。该调用用到了之前为视图控制器界面创建的XIB文件
  2. 设置About视图的标题。尅本地化该字符串
  3. 告诉导航控制器将新的视图控制器推到对战中——也就是打开并转场到该场景

运行结果:

添加颜色

  我们在IB中,有时候会看到Tint(色调)选项。使用此选项是为用户体验增加彩色主题的快速方法。需要注意的是,它与VIew区域中改变背景色是不同的。

  对UINavigationController来说,可以更改导航栏、工具栏和工具栏按钮的色调。为事物设置色调的工作由导航控制器进行管理,导航控制器会改变它管理的每个屏幕上该事物的颜色。

  打开故事面板,自行修改颜色。

  可能会遇到工具栏色调不起作用,那么我们可以用代码实现,在ViewController.m中的viewDidLoad方法下,添加

UIColor *sky = [UIColor colorWithDisplayP3Red:102.0/255.0 green:204.0/255.0 blue:255.0/255.0 alpha:1.0];self.navigationController.toolbar.barTintColor = sky;

  这时候颜色就添加完啦,本程序还添加了其他颜色,配色方案如下

用户界面元素 苹果蜡笔颜色 RGB
工具栏 SKY R:102 G:204 B:255
标题 snow(white) R:255 G:255 B:255
按钮 Mocha R:128 G:64 B:0

  但是我们上面的方法只能更改一个屏幕里面的颜色,以下代码是更改全部,在AppDelegate.m文件中

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {// Override point for customization after application launch.UIColor *Mocha = [UIColor colorWithDisplayP3Red:128.0/255 green:64.0/255.0 blue:0/255.0 alpha:1.0];[[UIButton appearance]setTitleColor:Mocha forState:UIControlStateNormal];[[UIBarButtonItem appearance] setTintColor:Mocha];return YES;
}

  其中,最后两行是通过appearance protocol协议修改按钮,工具栏按钮颜色。

  好了,导航控制器的使用就暂时介绍到这里咯。

1 标签栏控制器

  本想找clock程序作为用例的,模拟器上竟然没有。换成健康

  看到下面的健康数据,今天,数据来源这些选项了吧,这些是标签栏,每个栏对应不同的功能,而且有的栏里面还有多个屏幕。

工具栏的工作原理

  使用UITabBarController时,每个功能区域或标签栏都是根视图,实际上,标签栏控制器是应用程序真正的根视图,简单的画一下。

  标签栏控制器使用如下三个主要类:

  • UITabBarController管理标签栏选项卡中显示的视图控制器,并且还管理标签栏的用户交换,包括选择处理选中。如果存在5个以上选项卡,那么会展示More按钮。它也管理对额外选项卡的访问,并且管理选项卡的重新排序。
  • UITabBar是能呈现1至5个以上的选项卡的视图。每个选项卡都代表应用程序中一个不同的根视图。如果有5个以上的选项卡,那么特殊的More标签放置子在右边
  • UITabBarIter是标签栏的单个选项卡,包括两个属性分别用于标题和图像,以及一个属性用来自定义图像在被选中时的行为。

为CarValet添加标签栏

图片什么的之前已经导入了

  • 打开故事面板,选中下图

  • 选择Editor|Embed In|Tab Bar Controller

(PS,运行到这里,标签栏中应该是只有一个图标,圆形的还是方形的晚了)

  • 更换图标

  这时候是只有一个选项卡的,我就不运行了。现在我们将car image场景添加为第二个选项卡

  • 从Add/View场景中删除Car Images按钮
  • 从标签栏拉到Car Images场景,从Relationship Segue类别中选择视图控制器。这是就添加上去了。

  • 更换图标

  • 这时候运行程序,下面有两个选项卡了(PS我这是完整版,不要在意这些细节。。。)

  然而运行的时候发现reset没用

  进行以下步骤修改:

  • 在编辑器中打开CarImageViewController.h文件,将resetZoomButton的类别改成UIButton
  • 在iPhone故事面板中,选择CarImageViewController并将一个正常的按钮拖入到顶层视图,改标题为Reset Zoom
  • 设置约束,到顶部为系统默认,到后边缘为0
  • 拖拽一个从该按钮到.h文件中的resetZoomButton实例变量的关联
  • 拖拽一个从该按钮到car image视图中发送resetZoom消息的关联
  • 在与该按钮相对应的Attributes编辑器中的Control部分,将默认值设置为不可用

ok,运行程序就行啦。

最后一点,移动的Info

  我们通过代码的形式添加about到标签栏

  • 移除Add/View中的about按钮
  • 打开ViewController.m并删除对AboutVIewController.h的引用,删除aboutCarValet:方法以及在ViewController.h中的定义
  • 打开AppDelegate.m,导入AboutVIewController.h的引用。然后修改代码如下:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {// Override point for customization after application launch.UIColor *Mocha = [UIColor colorWithDisplayP3Red:128.0/255 green:64.0/255.0 blue:0/255.0 alpha:1.0];[[UIButton appearance]setTitleColor:Mocha forState:UIControlStateNormal];[[UIBarButtonItem appearance] setTintColor:Mocha];UITabBarController *tabBarController = (UITabBarController*)self.window.rootViewController;//1//2AboutViewController *aboutViewController = [[AboutViewController alloc]initWithNibName:@"AboutViewController"bundle:[NSBundle mainBundle]];UITabBarItem *aboutItem = [[UITabBarItem alloc]initWithTitle:@"About" //3image:[UIImage imageNamed:@"tag"]tag:0];[aboutViewController setTabBarItem:aboutItem];//4NSMutableArray *currentItems = [NSMutableArray arrayWithArray:tabBarController.viewControllers];//5[currentItems addObject:aboutViewController];//6[tabBarController setViewControllers:currentItems animated:NO];//7return YES;
}

注释:

  1. 获得对标签栏控制器的引用。
  2. 从XIB文件创建About视图控制器
  3. 为About场景创建一个标签栏选项,并设置合适的标题和图片
  4. 将About视图控制器的tabBarItem设置为新的标签栏选项。标签栏控制器会在设置标签栏选项的时候寻找该属性
  5. 基于那些由标签栏控制器进行管理的视图控制器,创建一个可变数组
  6. 将About场景添加到视图控制器数组的结尾。标签栏选项以数组中相同的顺序显示
  7. 在应用程序启动时,以不带动画效果的方式更新选项卡数组。如果该操作是在应用程序因用户行为而运行时发生,那么我们可能愿意以动画效果更新变化

      好了运行程序,再次贴图:

今天的介绍就到这里咯

我的另一个博客站点:Arnold-你们好啊

IOS开发入门(11)-导航控制器(1)相关推荐

  1. IOS开发UI篇—导航控制器属性和基本使用

    IOS开发UI篇-导航控制器属性和基本使用 一.导航控制器的一些属性和基本使用 1.把子控制器添加到导航控制器中的四种方法 (1) 1.创建一个导航控制器 UINavigationController ...

  2. iOS开发UI篇—多控制器和导航控制器简单介绍

    iOS开发UI篇-多控制器和导航控制器简单介绍 一.多控制器 一个iOS的app很少只由一个控制器组成,除非这个app极其简单.当app中有多个控制器的时候,我们就需要对这些控制器进行管理 有多个vi ...

  3. iOS(一):Swift纯代码模式iOS开发入门教程

    Swift纯代码模式iOS开发入门教程 项目初始化(修改为纯代码项目) 安装第三方库(以`SnapKit`库为例) 桥接OC库(QMUIKit) 封装视图并进行导航跳转 示例:使用 `TangramK ...

  4. iOS开发入门教程_iOS开发视频教程

    iOS开发入门教程 (Object-C.网络编程.多线程.蓝牙.二维码.Cocos2D.OpenGL) 适合人群:初级 课时数量:34课时 用到技术:IOS,Object-C,OpenGL,XCode ...

  5. android 艾特功能实现,IOS开发入门之iOS反编译实例之hook微信艾特所有人功能实现...

    本文将带你了解IOS开发入门iOS反编译实例之hook微信艾特所有人功能实现,希望本文对大家学IOS有所帮助. 研究了一段时间反编译逆向工程,只是略微了解了一些皮毛,最近忙的事情太杂,就简单写一下吧. ...

  6. IOS开发入门之一——Swift语言基础

    需要iOS视频资料可以加我微信: 1914532832  验证信息请注明:IOS开发 很多新人对IOS开发很迷茫,不知道从何下手?看完本系列,你将会觉得IOS入门其实很简单.要学习IOS开发,当然是先 ...

  7. IOS开发入门之Xcode使用教程详细讲解(全)

    摘要:本次的IOS开发入门学习中,Xcode使用教程详细讲解是本文要介绍的内容,Xcode是一个款强大的IDE开发环境,就像你在写Windows程序时需要VS2005一样 需要要Xcode为你写Mac ...

  8. linux 股票指南针,IOS开发入门之ios指南针

    本文将带你了解IOS开发入门之ios指南针,希望本文对大家学IOS有所帮助 参考http://blog.sina.com.cn/s/blog_4a37054201013nhr.html 可运行的代码如 ...

  9. android 地球坐标 火星坐标系,IOS开发入门之iOS开发火星坐标系与地球坐标系解析...

    本文将带你了解IOS开发入门iOS开发火星坐标系与地球坐标系解析,希望本文对大家学IOS有所帮助. iOS开发火星坐标系与地球坐标系解析. 在开发过程中,遇到一个问题,安卓和iOS传同样的经纬度给后台 ...

最新文章

  1. vue+antdesign导航菜单动态加载
  2. Windows定时删除某天前文件的批处理脚本
  3. 力扣第三题java_LeetCode 题解 | 力扣杯 LCP 06. 拿硬币
  4. Java利用Jakson实现序列化与反序列化操作
  5. Canopy聚类算法分析
  6. mysql 表设计 date_mysql 表 Date类型
  7. 1009家网站被约谈,一批恶意营销账号终于被关闭了
  8. 华为Y9s海外官网上架:升降式全面屏+侧面指纹识别
  9. 从孙子算经到中国剩余定理
  10. JavaScript学习初步
  11. 如何在VM ware虚拟环境下建立纯软双机热备
  12. 固高控制卡学习(vs2010,c++)(之一)
  13. 微服务统一认证与授权的 Go 语言实现
  14. RTCP 协议的 NACK 报文
  15. linux syslinux u盘,如何使用syslinux做一个启动U盘?
  16. 手机录像出现arn无响应
  17. Java电商平台-电商订单系统全解析
  18. latex 参考文献显示问号_终于用回vscode写LaTeX了
  19. python爬虫实践之爬取hao123音乐音乐导航
  20. 如何在HTML页面中编写大于号和小于号?(HTML实体)

热门文章

  1. 《黑客与画家》-读书笔记
  2. Flutter 不容错过的 7 大亮点 | Google I/O 精彩回顾
  3. locust之简介(1)
  4. MIUI V5八门神器不能用?一招教你搞定
  5. editplus如何设置保存后不生成备份文件
  6. 2021高考济南一中成绩查询,2021年济南重点高中名单及排名,济南高中高考成绩排名榜...
  7. 英特尔至强E7 v2处理器:2倍性能提升,3倍内存容量,4倍I/O带宽
  8. 一线程序员与二三线城市的困局,他们不能没有性生活
  9. 开放平台如何做接口的签名和加解密?
  10. w10不能访问网络计算机,Win10不能访问局域网其他电脑怎么办?解决Win10无法访问局域网...