一、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. 第19章 集合框架(3)-Map接口

    第19章 集合框架(3)-Map接口 1.Map接口概述 Map是一种映射关系,那么什么是映射关系呢? 映射的数学解释 设A,B是两个非空集合,如果存在一个法则,使得对A中的每一个元素a,按法则f,在 ...

  2. 转: Protobuf 的 proto3 与 proto2 的区别

    Protobuf 的 proto3 与 proto2 的区别   On 2015-07-17 19:16:00 By Soli   Protobuf 的 proto3 与 proto2 的区别 这是一 ...

  3. vijos P1915 解方程 加强版

    背景 B酱为NOIP 2014出了一道有趣的题目, 可是在NOIP现场, B酱发现数据规模给错了, 他很伤心, 哭得很可怜..... 为了安慰可怜的B酱, vijos刻意挂出来了真实的题目! 描述 已 ...

  4. mac os 下搭建android开发环境

    mac os 下搭建android开发环境 周银辉 mac os 下搭建android环境比较方便, 如下几个步骤: 1,安装jdk 先搞清楚自己是否已经安装,在命令行下:java -version, ...

  5. NOI2018准备Day14晚

    1个小时调处了前天晚上卡了一个晚上的数独,果然还是dfs回溯的问题. 1个小时做codevs2500城堡,然而并没有做出来 剩下1个小时,做了一道字符串的STL,空格和换行符 ,真心累啊...... ...

  6. 安卓开发:一种快速提取安卓app的UI图标资源的方法

    在做安卓设计时,找美工设计界面的漂亮图标是必不可少的,但是对于一个初创团队来说,请一个UI的成本其实也挺高的,此时对于一个偏技术的产品经理来说,从其他成熟的产品的apk中提取图标就是一个很便捷的方法, ...

  7. Ubuntu 下配置apache和APR

    软件环境:ubuntu14.04  虚拟机Vmware  软件:http://httpd.apache.org/  httpd-2.2.29.tar.gz  不需要单独下载APR. 1.解压apach ...

  8. NDK开发之一

    2015.07.22 Wiki_Tree: --NDK开发: --NDK特征: --MK文件编写规则: NDK开发: Ndk-build编译时会生成的两个同名的so库,位于不同的目录/project ...

  9. 分享 Ionic 开发 Hybrid App 中遇到的问题以及后期发布 iOS/Android 的方方面面

    此篇文章主要整理了最近在使用 Ionic 开发 Hybrid App 过程中遇到的一些疑难点以及后期发布生成 iOS 和 Android 版本过程中的种种问题. 文章目录 Ionic 简介和项目需求介 ...

  10. python基础-迭代器和生成器

    一.递归和迭代 1.递归:(问路示例) 递归算法是一种直接或者间接地调用自身算法的过程.在计算机编写程序中,递归算法对解决一大类问题是十分有效的,它往往使算法的描述简洁而且易于理解. 2.迭代:简单理 ...