UITabBarController的使用
UITabBarController是如下所示的视图控制器,有人叫它分栏视图控制器,也有人叫它选项卡控制器或页签视图控制器(通常我不称它为标签视图控制器主要是为了避免和UILabel标签混淆),它是在很多App种都能见到的一种视图控制器,如下图所示。
使用UITabBarController的场景很多,下图所示的微信和喜马拉雅听书都使用分栏视图控制器。
创建UITabBarController
// 创建分栏控制器
UITabBarController * tbc = [[UITabBarController alloc] init];
// 添加分栏控制器管理的视图控制器
tbc.viewControllers = @[视图控制器1, 视图控制器2, ... ];
// 将UITabBarController对象作为根视图控制器
self.window.rootViewController = tbc;
下图展示了UITabBarController的构成。
和UINavigationController非常类似,UITabBarController也包含一个UITabBar(选项卡栏),上面有若个个UITabBarItem(选项卡项),每个选项卡项又由标题、图片和徽章构成。
将UINavigationController加入到UITabBarController中
UINavigationController和UITabBarController混合使用在App开发中还是很常见的,大致有两种使用模式:
- UITabBarController各子界面是独立的导航关系,互不影响
UIViewController *viewController1 = [[FirstViewController alloc] initWithNibName:@”FirstViewController” bundle:nil];
UIViewController *viewController2 = [[SecondViewController alloc] initWithNibName:@”SecondViewController” bundle:nil];
UINavigationController* nav1 = [[UINavigationController alloc] initWithRootViewController:viewController1];
UINavigationController* nav2 = [[UINavigationController alloc] initWithRootViewController:viewController2];
UITabBarController* tabBarController = [[UITabBarController alloc] init];
tabBarController.viewControllers = [NSArray arrayWithObjects:nav1, nav2, nil];
self.window.rootViewController = tabBarController;
- 应用整体是一个导航关系,只在根界面上分若干选项卡页
UIViewController *viewController1 = [[FirstViewController alloc] initWithNibName:@”FirstViewController” bundle:nil];
UIViewController *viewController2 = [[SecondViewController alloc] initWithNibName:@”SecondViewController” bundle:nil];
UITabBarController* tabBarController = [[UITabBarController alloc] init];
tabBarController.viewControllers = [NSArray arrayWithObjects:viewController1, viewController2, nil];
UINavigationController* navController = [[UINavigationController alloc] initWithRootViewController:tabBarController];
self.window.rootViewController = navController;
多于4个分栏的处理
通常情况下分栏条最多支持5个视图控制器,如果超过5个,只显示4个,第5项变成了一个More,点击后会出现一个UITableViewController用于放置多余的视图控制器,通过导航可以切换,也可以对其进行编辑,如下图所示。
显示上次选中的视图
如果我们希望在下次打开App的时候能够恢复到上次选中的视图(这应该是一个非常好的用户体验),那么我们可以使用NSUserDefaults来记录用户最后选中了第几个分栏。记录用户的喜好和习惯是构造一个优秀应用的基础,这能让用户感觉到在使用我们的App时更加得心应手,很多应用都有用户偏好设置,我们如何存储这些偏好设置呢?每个应用包种都有一个info.plist文件,它是一个键值对映射,可以方便的存储用户偏好,可以通过NSUserDefaults来访问plist文件。
NSUserDefaults提供了 standardUserDefaults 类方法来获得NSUserDefaults对象,接下来就是键值对映射的读写操作,使用起来非常的简单。
// 实现UITabBarControllerDelegate协议中的方法在选中某个视图控制器时回调
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
NSUserDefaults *userDef = [NSUserDefaults standardUserDefaults];
// 将用户选中的视图控制器的索引通过NSUserDefaults对象存储起来
[userDef setInteger:tabBarController.selectedIndex forKey:@"selectedTabIndex"];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// ... ...
NSUserDefaults *userDef = [NSUserDefaults standardUserDefaults];
// 将UITabBarController对象选中的索引设置为plist存储的选中索引
tbc.selectedIndex = [userDef integerForKey:@"selectedTabIndex"];
// ... ...
}
通过NSUserDefaults对象可以完成下列操作:
- 注册出厂设置:使用 registerDefaults:方法,这个方法的参数是一个NSDictionary的对象,其中存储的是和偏好设置相关的键值对
- 读取用户偏好设置:通过 xxxForKey:系列方法可以根据键获得对应类型的值
- 修改用户偏好设置:通过 setXXX:forKey:系列方法可以设置键值对映射
说明:还可以通过为应用程序出啊构建一个叫做"settings bundle"的东西来注册并修改用户的偏好设置。
获取UITabBarController中的所有子视图控制器
viewControllers属性可以帮助我们获得分栏视图控制器上所有的子视图控制器的数组,我们可以通过下标运算来获得某个子视图控制器。
UITabBar和UITabBarItem
- 图片:selectedImage属性
- 徽章:badgeValue属性
- 颜色:tintColor属性
UITabBarController的定制
如何定制一个喜马拉雅听书那样的UITabBarController呢?我们可以继承UITabBarController并隐去自带的UITabBar,然后对整个下面的区域进行完全定制。XIB的可视化效果和关键代码如下所示:
//
// CDMyTabBarController.m
// day082506
//
// Created by LUOHao on 15/8/25.
// Copyright (c) 2015年 jackfrued. All rights reserved.
//
#import "CDMyTabBarController.h"
@interface CDMyTabBarController () {
UIView *bottomView;
}
@end
@implementation CDMyTabBarController
- (void)viewDidLoad {
[super viewDidLoad];
// 隐去原有的分栏条
self.tabBar.hidden = YES;
// 通过XIB加载一个视图替换原来的分栏条
bottomView = [[[NSBundle mainBundle] loadNibNamed:@"CDMyTabBarView" owner:self options:nil] firstObject];
CGRect rect = self.view.bounds;
bottomView.frame = CGRectMake(0, rect.size.height - 92, rect.size.width, 92);
[self.view addSubview:bottomView];
for (UIView *tempView in bottomView.subviews) {
if ([tempView isKindOfClass:[UIButton class]]) {
UIButton *tempButton = (id)tempView;
[tempButton addTarget:self action:@selector(tabBarButtonItemClicked:) forControlEvents:UIControlEventTouchUpInside];
}
}
}
- (void)tabBarButtonItemClicked:(UIButton *)sender {
// 根据按钮的tag值确定选中的分栏的索引
self.selectedIndex = sender.tag - 200;
// 将所有按钮的设置为未选中状态
for (UIView *tempView in bottomView.subviews) {
if ([tempView isKindOfClass:[UIButton class]]) {
UIButton *tempButton = (id)tempView;
tempButton.selected = NO;
}
}
// 将点击的按钮设置为选中状态
sender.selected = YES;
}
@end