一、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左右,

可以参考链接https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/MobileHIG/IconsImages/IconsImages.html

再来看下面这张图,它描绘了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详解的更多相关文章

  1. UI第六节——UINavigationController 详解

    1. UINavigationController 是一个容器类.里面盛放的是UIViewController. 容器的意思是,如果你不放入UIViewController,里面就是空的,什么也没有. ...

  2. 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的无状态模 ...

  3. centos shell脚本编程2 if 判断 case判断 shell脚本中的循环 for while shell中的函数 break continue test 命令 第三十六节课

    centos  shell脚本编程2 if 判断  case判断   shell脚本中的循环  for   while   shell中的函数  break  continue  test 命令   ...

  4. 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. 大白话5分钟带你走进人工智能-第二十六节决策树系列之Cart回归树及其参数(5)

                                                    第二十六节决策树系列之Cart回归树及其参数(5) 上一节我们讲了不同的决策树对应的计算纯度的计算方法, ...

  6. Java基础学习总结(33)——Java8 十大新特性详解

    Java8 十大新特性详解 本教程将Java8的新特新逐一列出,并将使用简单的代码示例来指导你如何使用默认接口方法,lambda表达式,方法引用以及多重Annotation,之后你将会学到最新的API ...

  7. HTTP协议 (六) 状态码详解

    HTTP协议 (六) 状态码详解 HTTP状态码,我都是现查现用. 我以前记得几个常用的状态码,比如200,302,304,404, 503. 一般来说我也只需要了解这些常用的状态码就可以了.  如果 ...

  8. C++11 并发指南六(atomic 类型详解四 C 风格原子操作介绍)

    前面三篇文章<C++11 并发指南六(atomic 类型详解一 atomic_flag 介绍)>.<C++11 并发指南六( <atomic> 类型详解二 std::at ...

  9. C++11 并发指南六(atomic 类型详解三 std::atomic (续))

    C++11 并发指南六( <atomic> 类型详解二 std::atomic ) 介绍了基本的原子类型 std::atomic 的用法,本节我会给大家介绍C++11 标准库中的 std: ...

随机推荐

  1. 洛谷U4859matrix[单调栈]

    题目描述 给一个元素均为正整数的矩阵,上升矩阵的定义为矩阵中每行.每列都是严格递增的. 求给定矩阵中上升子矩阵的数量. 输入输出格式 输入格式: 第一行两个正整数n.m,表示矩阵的行数.列数. 接下来 ...

  2. HBASE 安装法

    http://www.cnblogs.com/nexiyi/p/hbase_intro_94.html

  3. linux常用指令

    整理下来的linux常用指令 mount [-t 文件系统] 设备文件名 挂载点挂载命令,一般用于在挂载ISO,或者其他比如U盘等设备时使用,[-t iso9660]为固定格式,可写可不写,非必写项. ...

  4. 银行卡BIN: Bank Identification Number

    What is a 'Bank Identification Number - BIN'A bank identification number (BIN) is the initial four t ...

  5. ReactJS基础视频教程

    React是什么?React.js 是 Facebook 推出的一个用来构建用户界面的 JavaScript 库.Facebook开源了React,这是该公司用于构建反应式图形界面的JavaScrip ...

  6. .Net 闭包理解

    .Net 闭包理解 这个东西初看是比较难懂,但是一旦理解之后就很容易了,做笔记以加深印象.且看这题 example.1 class Program { static void Main(string[ ...

  7. Python基础+Pythonweb+Python扩展+Python选修四大专题 超强麦子学院Python35G视频教程

    [保持在百度网盘中的, 可以在观看,嘿嘿 内容有点多,要想下载, 回复后就可以查看下载地址,资源收集不易,请好好珍惜] 下载地址:http://www.fu83.cc/ 感觉文章好,可以小手一抖 -- ...

  8. SQLite剖析之编程接口详解

    前言 使用过程根据函数大致分为如下几个过程: sqlite3_open() sqlite3_prepare() sqlite3_step() sqlite3_column() sqlite3_fina ...

  9. Java 理论与实践: 处理 InterruptedException

    捕捉到它,然后怎么处理它? 很多 Java™ 语言方法,例如 Thread.sleep() 和 Object.wait(),都可以抛出InterruptedException.您不能忽略这个异常,因为 ...

  10. 关于dll

    今日看到一个不带dllmain的dll,忽然觉得有点奇怪,然后查了一下,原来dll还可以不需要dllmain,甚至可以自己定义入口 先mark以下的资料,有空再总结一下...同时dll劫持,有必要亲身 ...