UI第十六节——UITabBarController详解
一、UITabBarController主要用来管理你提供的content view controllers,而每一个 content view controller则负责管理自己的view层级关系,通常,当你的程序想要提供一些平行(同一个等级的)的不同界面,而恰好这些界面使用到的数据是一类的,或者功能是一个系列的,那 tab bar interface 是非常有用的. 在这样的 tab bar interface界面中,你可以设置许多的 tab ,每一个 tab则一定要指定一个content view controller,当某个tab被点击时,UITabBarController就会选中该tab并且显示该viewController所持有的content view.在apple官网上有一张关于UITabBarController的图片,如下:

观察上图,最下面的那个Tab bar,这是由UITabBarController自己负责维护的,就像UINavigation Bar是由UINavigationController负责维护一样,不建议被修改,但如果实在需要改变的话,只能通过UITabBarController提供的方法去修改。
你有没有发现,绝大多数的iOS程序,如果他用到了UITabBarController,那么他的外观就像上图,Tab bar默认在下面,但有时我们又希望将他显示到最上面去,就像android的联系人程序一样,其实只要几句代码就行了:
CGRect frame = CGRectMake(0, 20, 320, 44) tabBarController.tabBar.frame = frame;
呵呵,这样不就可以了,你想放哪放哪,不过可别太难看了。
二、一个标准的 tab bar interface 通常由下列对象组成:
1.一个 UITabBarController 对象
2.每一个tab 都必须有一个content view controller(所以UITabBarController有一个属性是viewControllers)
3.一个可选的delegate对象
注意了:通常而言,UITabBarController一般作为应用程序的rootViewController,而且它不能作为UINavigationController的rootViewController.
所以初始化的代码一般这样写:

self.viewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil];
ViewControllerA *A = [[ViewControllerA alloc]initWithNibName:@"ViewControllerA" bundle:nil];
ViewControllerB *B = [[ViewControllerB alloc]initWithNibName:@"ViewControllerB" bundle:nil];
ViewControllerC *C = [[ViewControllerC alloc]initWithNibName:@"ViewControllerC" bundle:nil];
ViewControllerD *D = [[ViewControllerD alloc]initWithNibName:@"ViewControllerD" bundle:nil];
ViewControllerE *E = [[ViewControllerE alloc]initWithNibName:@"ViewControllerE" bundle:nil];
UITabBarController *tabBarController = [[UITabBarController alloc]init];
A.tabBarItem = [[UITabBarItem alloc]initWithTabBarSystemItem:UITabBarSystemItemBookmarks tag:0];
self.viewController.tabBarItem = [[UITabBarItem alloc]initWithTabBarSystemItem:UITabBarSystemItemContacts tag:1];
B.tabBarItem = [[UITabBarItem alloc]initWithTabBarSystemItem:UITabBarSystemItemDownloads tag:2];
C.tabBarItem = [[UITabBarItem alloc]initWithTabBarSystemItem:UITabBarSystemItemHistory tag:3];
D.tabBarItem = [[UITabBarItem alloc]initWithTabBarSystemItem:UITabBarSystemItemSearch tag:4];
E.tabBarItem = [[UITabBarItem alloc]initWithTabBarSystemItem:UITabBarSystemItemTopRated tag:5];
tabBarController.viewControllers = @[self.viewController,A,B,C,D,E];
tabBarController.customizableViewControllers = @[B,C,D,E];
[tabBarController setSelectedIndex:2];
tabBarController.delegate = self; // CGRect frame = CGRectMake(0, 20, 320, 44); // tabBarController.tabBar.frame = frame; self.window.rootViewController = tabBarController;

你应该像上面那样,为每一个viewController指定一个tabBarItem,当然你也可以这样初始化
A.tabBarItem = [[UITabBarItem alloc]initWithTitle:<#(NSString *)#> image:<#(UIImage *)#> tag:<#(NSInteger)#>];
从而达到自定义tab bar item外观的目的,而不必使用系统提供好的,但此时你使用的图片大小要有规定了,一般ipad在60*60,iPhone在30*30左右,
再来看下面这张图,它描绘了UITabBarController和它的属性viewControllers、customizableViewControllers和selectedViewController等的关系

如果你的viewControllers属性添加了多于五个的items,那tab bar controller将会自动插入一个特殊的view controller,称为 More view controller,该 controller 将会负责管理多于的items,这个More view controller提供一个自定义的界面,用table的方式呈现多余的view controller,并且view controller的数量是不限制的。对于这个more view controller ,UITabBarController 通过一个属性----moreNavigationController持有它的引用,但看名字就知道他是一个UINavigationController对象,所有我们可以修改它的一些属性,如:
UINavigationController *nav = tabBarController.moreNavigationController;
[nav setNavigationBarHidden:YES];
当然,如不是必须,最好不要修改它。
三、在创建一个tab bar interface之前,你应该考虑清楚程序是否真的需要使用该布局,而且应该在正确的地方使用它……通常通过下面这些方式使用:
1.作为window的root view controller
2.作为 split view interface(iPad专有界面,不知道的可以百度下)中的其中一个一个view controller
3.作为modal view使用
4.作为UIPopoverController(iPad专有)的content view
四、在tab bar interface创建好后,我们可以用代码动态的修改它,如:增加或删除tab项,对于这种操作,通常我们需要重新指派UITabBarController的viewConrollers属性来进行,有人可能要问了,为什么要重新指派,viewController不是一个数组吗,不能直接通过数组的remove方法直接删除吗,可别忘了,这个属性的类型是个NSArray,不能进行删除,添加的。我们知道,当tab bar interface界面显示后,我们只能在某一时刻操作一个界面,因此,修改viewControllers属性必须在某个content viewController中完成,我们可以通过UIViewController的属性 tabBarController来获得UITabBarController的引用,就像获得UINavigationController的引用一样,修改代码如下:

NSMutableArray* newArray = [NSMutableArray arrayWithArray:self.tabBarController.viewControllers];
[newArray removeObject:self];
[self.tabBarController setViewControllers:newArray animated:YES];
五、当你点击某个tab项时,它对应的content viewController会得到显示,
但有时也许我们就是不希望某个被你点击的view得到显示,如:某个viewController所需的数据还没有完成加载,或者必须等某个登陆界面 完成登陆后
才能激活其他viewController,此时你可以实现UITabBarControllerDelgate中的方法
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController NS_AVAILABLE_IOS(3_0)
通过设置返回值来禁止某个viewController能否被选中,如下:


- (BOOL)tabBarController:(UITabBarController *)aTabBar
shouldSelectViewController:(UIViewController *)viewController
{ if (![self hasValidLogin] && (viewController != [aTabBar.viewControllers objectAtIndex:0]) )
{ // Disable all but the first tab. return NO;
} return YES;
}

当然你也可以通过代码手动去选择某个viewController,只要设置UITabBarController的属性selectedViewController 或者 selectedIndex(从0开始),但此时代理的方法是无效的,也就是说,如果你通过代码来选中某个viewController的话,则肯定是可以选中的。。。
六、其实UITabBarController还允许你对viewControllers进行排序,你可以使任意一个viewController出现在第一个tab项中,上面我们有提到moreNavigationController,当tabs超过5个时,也就是viewControllers的个数超过5个时,最后一个的tab item默认为more,然后那些没能显示在tab上的viewController便可通过moreNavigationController以列表的形势显示,那是不是那些没能在tab上显示的viewController就永远只能在moreNavigationController的列表中显示了??当然不是,当我么点击more tab时会出现下面左图的界面,然后再点击navigationBar左边的编辑按钮时会出现下面的右图,此时你可以把这些显示的tab直接拉到下面的 tab bar中,从而达到自定义tab的功能

那如果我希望某个viewController一直在tab上显示,二不希望用户将其排列到more tab中去,那该怎么办呢。。。。UITabBarController有个属性customizableViewControllers
由它来决定哪些viewController允许重排列。。不过这里要注意了,默认情况下customizableViewControllers 和 viewControllers属性包含的内容是一样的,你可以手动设置它为viewControllers的字集(只能是字集),但当你重新更新了viewControllers时,customizableViewControllers又会默认和viewControllers相等,希望表达清楚了。。。
七、

看看上面的图,是不是和应用程序的badge很像,当某个tab有信息需要你处理时,显示这个能很好的引起用户的注意,而你只需这样做
if (numberOfNewItems == 0)
self.tabBarItem.badgeValue = nil; else self.tabBarItem.badgeValue = [NSString stringWithFormat:@"%d", numberOfNewItems];
self 是 viewContrller ,不过要注意了,这里的badgeValue是个NSString类型的,不要和下面的弄混了
[UIApplication sharedApplication].applicationIconBadgeNumber = 2
通常情况下,当我们点击显示了badge的那个tab后,这个红色的提示就应该消失。呵呵,可别忘了,当你切换tab时,viewController的声明周期可是一样的,它会执行那些
viewDidAppear 、viewDidDisappear等方法,所以最好的办法就是在该viewContrller的
-(void)viewDidAppear:(BOOL)animated方法中,将其重置为空,
如:self.tabBarItem.badgeValue = nil;
八、UITabBarController是否能旋转呢?那要看它的那些viewControllers了,如果在viewControllers中只要有一个viewController不支持某个方向的旋转,那UITabBarControlelr就也不能旋转到该方向。再来看看它的一些代理方法,我就简单描述下:
//当你选中某个tab 项时调用,我们可以在这里做一些操作,如隐藏状态栏,导航栏什么的。
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
//当点击more后出现moreNavigationController画面时,点击那个edit按钮时触发
- (void)tabBarController:(UITabBarController *)tabBarController willBeginCustomizingViewControllers:(NSArray *)viewControllers NS_AVAILABLE_IOS(3_0)
//下面两个方法在点击那个done按钮时触发
- (void)tabBarController:(UITabBarController *)tabBarController willEndCustomizingViewControllers:(NSArray *)viewControllers changed:(BOOL)changed NS_AVAILABLE_IOS(3_0)
- (void)tabBarController:(UITabBarController *)tabBarController didEndCustomizingViewControllers:(NSArray*)viewControllers changed:(BOOL)changed
【转自】http://www.cnblogs.com/ctaodream/p/3307745.html
如果对你有帮助,请关注我哦!
UI第十六节——UITabBarController详解的更多相关文章
- UI第六节——UINavigationController 详解
1. UINavigationController 是一个容器类.里面盛放的是UIViewController. 容器的意思是,如果你不放入UIViewController,里面就是空的,什么也没有. ...
- ASP.NET MVC深入浅出系列(持续更新) ORM系列之Entity FrameWork详解(持续更新) 第十六节:语法总结(3)(C#6.0和C#7.0新语法) 第三节:深度剖析各类数据结构(Array、List、Queue、Stack)及线程安全问题和yeild关键字 各种通讯连接方式 设计模式篇 第十二节: 总结Quartz.Net几种部署模式(IIS、Exe、服务部署【借
ASP.NET MVC深入浅出系列(持续更新) 一. ASP.NET体系 从事.Net开发以来,最先接触的Web开发框架是Asp.Net WebForm,该框架高度封装,为了隐藏Http的无状态模 ...
- centos shell脚本编程2 if 判断 case判断 shell脚本中的循环 for while shell中的函数 break continue test 命令 第三十六节课
centos shell脚本编程2 if 判断 case判断 shell脚本中的循环 for while shell中的函数 break continue test 命令 ...
- centos linux系统日常管理3 服务管理ntsysv,chkconfig,系统日志rsyslog,last ,lastb ,exec,xargs,dmesg,screen,nohup,curl,ping ,telnet,traceroute ,dig ,nc,nmap,host,nethogs 第十六节课
centos linux系统日常管理3 服务管理ntsysv,chkconfig,系统日志rsyslog,last ,lastb ,exec,xargs,dmesg,screen,nohup,cur ...
- 大白话5分钟带你走进人工智能-第二十六节决策树系列之Cart回归树及其参数(5)
第二十六节决策树系列之Cart回归树及其参数(5) 上一节我们讲了不同的决策树对应的计算纯度的计算方法, ...
- Java基础学习总结(33)——Java8 十大新特性详解
Java8 十大新特性详解 本教程将Java8的新特新逐一列出,并将使用简单的代码示例来指导你如何使用默认接口方法,lambda表达式,方法引用以及多重Annotation,之后你将会学到最新的API ...
- HTTP协议 (六) 状态码详解
HTTP协议 (六) 状态码详解 HTTP状态码,我都是现查现用. 我以前记得几个常用的状态码,比如200,302,304,404, 503. 一般来说我也只需要了解这些常用的状态码就可以了. 如果 ...
- C++11 并发指南六(atomic 类型详解四 C 风格原子操作介绍)
前面三篇文章<C++11 并发指南六(atomic 类型详解一 atomic_flag 介绍)>.<C++11 并发指南六( <atomic> 类型详解二 std::at ...
- C++11 并发指南六(atomic 类型详解三 std::atomic (续))
C++11 并发指南六( <atomic> 类型详解二 std::atomic ) 介绍了基本的原子类型 std::atomic 的用法,本节我会给大家介绍C++11 标准库中的 std: ...
随机推荐
- Microsoft Azure Point to Site VPN替代方案
Microsoft Azure提供了Point to Site VPN,但有时候这并不能满足我们的需求,例如:Point to Site VPN是SSTP VPN,只能支持Window客户端拨入,而且 ...
- MMORPG大型游戏设计与开发(服务器 游戏场景 多线程)
多线程在随着cpu发展应用的是越来越多,游戏场景因为其在服务器所占的数据量与逻辑复杂度的原因必须依赖于它.为什么场景要采用多线程?场景的线程是怎样的?场景的线程又是如何创建的?场景的线程又是怎样管理的 ...
- python 聊天室
server端程序 # -*- coding: utf-8 -*- #!/usr/bin/python """ """ import soc ...
- [转载]python:open/文件操作
open/文件操作f=open('/tmp/hello','w') #open(路径+文件名,读写模式) #读写模式:r只读,r+读写,w新建(会覆盖原有文件),a追加,b二进制文件.常用模式 如:' ...
- Log4j
[1]从零开始 a). 新建Java Project>>新建package>>新建java类: b). import jar包(一个就够),这里我用的是log4j-1.2.14 ...
- python基础之dict、set及字符
python基础之dict.set及字符串处理 本节内容 字典介绍及内置方法 集合介绍 字符串处理 1.字典介绍及内置方法 字典是python中唯一的映射类型,采用键值对(key-value)的形式存 ...
- angular监听
监听中第三个参数,何时使用true? true的意思是“深度监听” 1.当监听对象属性变化时,而你监听的对象写得是对象,此时要用深度监听true: 2....... 监听耗资源,用完关闭 var wa ...
- vector容器删除某些元素且释放内存
1,size和capacity size: 指目前容器中实际有多少元素,对应的resize(size_type)会在容器尾添加或删除一些元素,来调整容器中实际的内容,使容器达到指定的大小. capac ...
- 使用startActivityForResult场景模拟
效果图如下,当我从第一个界面选择供应商的时候,我希望能得到第二个界面选择的供应商的值: 具体代码,这里第二个参数为自定义的大于等于0的数字,用来标记当前跳转. Intent i1 = new Inte ...
- 生成 PDF 全攻略【2】在已有PDF上添加内容
项目在变,需求在变,不变的永远是敲击键盘的程序员..... PDF 生成后,有时候需要在PDF上面添加一些其他的内容,比如文字,图片.... 经历几次失败的尝试,终于获取到了正确的代码书写方式. 在此 ...