UITabBarController是IOS中很常用的一个viewController,例如系统的闹钟程序,ipod程序等。UITabBarController通常作为整个程序的rootViewController,而且不能添加到别的container viewController中(在后面会详细解释)
先通过UITabBarController的层级图来分析一下它的结构组成
它是由下方的TabBar和用来显示内容的Custom content组成,整个界面又可以认为是TabBarController的显示视图
下面先说一下标签控制器和导航控制器在使用上的区别:
1、导航视图控制器,管理的控制器之间存在层级关系(依赖关系)
标签视图控制器,管理的控制器之间是并列关系(同时存在,互不干扰)
2、管理方式
导航控制器以栈的形式管理多个试图控制器,push入栈,pop出栈,当返回上一界面时,空间回收
标签视图控制器,以不可变数组管理,而且创建时必须要全部指定所管理的多个视图控制器,而且多个视图控制器同时存在,空间不回收
3、视图控制器之间的嵌套
正常用法:标签视图控制器管理多个导航控制器,每个导航控制器又管理多个单视图控制器(每个界面都有导航条,导航条都是不同的,单视图控制器可以自定义导航内容)
非常用法:导航控制器管理标签控制器,标签控制器用来管理多个单视图控制器(每个界面都有导航条,但是导航条都是一样的,单视图控制器不可以自定义导航条内容),这种用法不符合逻辑,很少使用
导航控制器、标签控制器都是多视图控制器,可以管理多个视图控制器,但是UITableViewController、UIViewController是单视图控制器,不可以管理视图控制器,只能管理视图
接下来再熟悉一下视图下面的UITabBar的结构组成
注意:UITabBarButton在UITabBar中得位置是均分的,UITabBar的高度为49
注意:UITabBarButton的一些属性是通过tabBarItem来改变的(后面的代码会详细介绍用法)
下面主要说一下UITabBar的注意事项:
1、UITabBar上最多可以显示5个TabBarButton,当我们往UITabBarController中添加的viewController超过5个的时候,最后一个一个就会自动变成more图标,按照设置的viewControlles的顺序,显示前四个viewController的tabBarItem,后面的tabBarItem将不再显示。当点击more的时候将会弹出一个标准的navigationViewController,里面放有其它未显示的的viewController,并且带有一个edit按钮,通过点击该按钮可以进入类似与ipod程序中设置tabBar的编辑界面。编辑界面中默认所有的viewController都是可以编辑的,我们可以通过设置UITabBarController的customizableViewControllers属性来指定viewControllers的一个子集,即只允许一部分viewController是可以放到tabBar中显示的。但是这块儿要注意一个问题就是每当UITabBarController的viewControllers属性发生变化的时候,customizableViewControllers就会自动设置成和viewControllers一致,即默认的所有的viewController都是可以编辑的,如果我们要始终限制只是某一部分可编辑的话,记得在每次viewControlles发生改变的时候,重新设置一次customizableViewControllers。
2、UITabBarController默认只支持竖屏,当设备方向放生变化时候,它会查询viewControllers中包含的所有ViewController,仅当所有的viewController都支持该方向时,UITabBarController才会发生旋转,否则默认的竖向
此处需要注意当UITabBarController支持旋转,而且发生旋转的时候,只有当前显示的viewController会接收到旋转的消息
3、如果UITabBarController有N个子控制器,那么UITabBar内部就会有N 个UITabBarButton作为子控件与之对应,点击对应的UITabBarButton就会显示对应的视图
UITabBar自己有一些方法是可以改变自身状态,但是对于UITabBarController自带的tabBar,我们不能直接去修改其状态。任何直接修改tabBar的操作将会抛出异常
接下来用代码表述UITabBarController的用法:
// 1、创建3个单视图控制器,分别加到对应的导航控制器上
FirstViewController *firstVC = [[[FirstViewController alloc]init]autorelease];
UINavigationController *firstNav = [[[UINavigationController alloc]initWithRootViewController:firstVC]autorelease];
firstVC.view.backgroundColor = [UIColor redColor];
SecondViewController *secondVC = [[[SecondViewController alloc]init]autorelease];
UINavigationController *secondNav = [[[UINavigationController alloc]initWithRootViewController:secondVC]autorelease];
secondVC.view.backgroundColor = [UIColor orangeColor];
ThirdViewController *thirdVC = [[[ThirdViewController alloc]init]autorelease];
UINavigationController *thirdNav = [[[UINavigationController alloc]initWithRootViewController:thirdVC]autorelease];
thirdVC.view.backgroundColor = [UIColor cyanColor];
// 2、创建一个不可变数组,装入3个导航控制器
NSArray *controllers = @[firstNav, secondNav, thirdNav];
// 3、创建一个标签视图控制器
UITabBarController *tabBarController = [[[UITabBarController alloc]init]autorelease];
// 4、设置标签控制器的被控制对象(3个导航控制器)
tabBarController.viewControllers = controllers;
// 5、将标签控制器设置为window的根视图
self.window.rootViewController = tabBarController;
// 设置标签视图控制器的一些属性:
// 设置三个导航控制器在tabBarController上的按钮的标题和背景图片
firstNav.tabBarItem.title = @"First";
firstNav.tabBarItem.image = [UIImage imageNamed:@"qr_toolbar_light_up_hl"];
secondNav.tabBarItem.title = @"Second";
secondNav.tabBarItem.image = [UIImage imageNamed:@"tabbar_contacts"];
thirdNav.tabBarItem.title = @"Third";
thirdNav.tabBarItem.image = [UIImage imageNamed:@"tabbar_discover"];
// 设置标签栏的渲染颜色(图标点击后的颜色)
tabBarController.tabBar.tintColor = [UIColor purpleColor];
// 设置整个tabBar的颜色(如果不设置,tabBar默认是毛玻璃效果)
// tabBarController.tabBar.barTintColor = [UIColor whiteColor];
// 设置某个tabBarItem的右上角的小角标内容(NSString)
firstNav.tabBarItem.badgeValue = @"新消息";
// 有两种方式可以往UITabBarController中添加子控制器
UIViewController *con1 = [[UIViewController alloc]init];
con1.view.backgroundColor = [UIColor grayColor];
UINavigationController *nav1 = [[UINavigationController alloc]initWithRootViewController:con1];
[con1 release];
nav1.tabBarItem.title = @"第四个按钮";
// 第一种添加方法(该方法如果放在方法tabBarController.viewControllers = controllers之后,设置无效,原因不详)
// [tabBarController addChildViewController:nav1];
// 第二种添加方法(该方法重新设置了viewControllers,会把前面的设置覆盖,所以也可以用这个方法删除某个按钮)
// tabBarController.viewControllers = @[firstNav, secondNav, thirdNav, nav1];
// 设置tabBar的样式(没多大用处)
tabBarController.tabBar.barStyle = UIBarStyleDefault;
/*
UIBarStyleDefault
UIBarStyleBlack // 黑色毛玻璃效果
UIBarStyleBlackOpaque
UIBarStyleBlackTranslucent
*/
// 设置标签视图控制器默认选中的标签(系统默认选择第0个)
tabBarController.selectedIndex = 0;
// 设置标签视图控制器默认选中的视图控制器(效果和选择标签一样)
// tabBarController.selectedViewController = firstNav;
// 设置代理
tabBarController.delegate = self;
代理(委托)方法的实现(其中的修改TabBarButton的代理方法只有当 TabBarButton的数量是5个或以上时才有意义)
#pragma mark - tabBarController Delegate
// 将要选中某一个控制器
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController
{
// 设置不让选中某一个控制器(其实这里的设置无效:因为三个按钮是UINavigationController类型)
// 这里只是介绍这种设计思想,让大家知道有这么一个方法
// if ([viewController isKindOfClass:[ThirdViewController class]]) {
// return NO;
// }
// return YES;
// 用别的方法实现
UINavigationController *nav = (UINavigationController *)[[tabBarController viewControllers] objectAtIndex:2];
if ([viewController isEqual:nav]) {
return NO;// 第三个按钮不让选择
}
return YES;
}
// 已经选中某一个控制器
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
{
// 如果选择了第二个控制器,弹出警告
if (tabBarController.selectedIndex == 1) {
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"警告" message:@"18岁以下禁止进入" delegate:self cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
[alert show];
[alert release];
}
}
// 将要定制这些导航控制器(移动、删除操作等)
- (void)tabBarController:(UITabBarController *)tabBarController willBeginCustomizingViewControllers:(NSArray *)viewControllers
{
// 查看定制前导航控制器数组的对象的排列顺序
NSLog(@"%@", viewControllers);
}
// 导航控制器定制完成
- (void)tabBarController:(UITabBarController *)tabBarController didEndCustomizingViewControllers:(NSArray *)viewControllers changed:(BOOL)changed
{
// 查看定制后导航控制器数组的对象的排列顺序
NSLog(@"%@", viewControllers);
}
下面是运行的两个效果图