一、 UITabBarController的原理
1.1 基本概念
父控制器
:通过标签控制器管理多个子控制器,标签控制器就称为父控制器
子控制器
:添加到标签控制器里的控制器都做为标签控制器的子控制器
标签栏
:也叫选项卡栏,方便用户切换到对应的界面,当往标签控制器里添加子控制器,标签栏就会有序的自动生成对应的标签
标签栏按钮
:也叫标签,UITabBarButton,这个类只有apple内部开发人员才能使用
1.2 UITabBarController原理
当UITabBarController做为Window的根控制器时,程序一启动,
UITabBarController就会一次性初始化所有子控制器,但是默认只加载第一个控制器视图,其他视图控制器只初始化,但默认不会加载,只有在需要显示的时候才调用loadView方法加载。
特殊情况:在AppDelegate中设置其他的子控制器视图的背景颜色,就会提前加载该控制器视图,但不显示该视图。
每一个控制器视图
只加载一次,就会一直存在内存中
,当切换子控制器时直接显示,不显示在屏幕上的子控制器不会被销毁。当遇到内存警告时,会释放掉没有加载的子控制器。每个视图控制器都有一个tabBarController属性
,通过它可以访问所在的UITabBarController,而且对于UITabBarController的直接子视图,其tabBarController属性相当于它的父视图parentViewController。每个视图控制器都有一个
tabBarItem
属性,通过它控制视图在UITabBarController的tabBar中的显示信息tabBarItem的image属性必须是
png格式(建议大小32*32)
,并且打开alpha通道否则无法正常显示。
当往UITabBarController添加子控制器,标签栏就会有序的自动生成对应的UITabBarButton对象,有多少个子控制器,标签栏就有多少个UITabBarButton对象, 但是子控制器的数量超过5个的时候,标签栏上的第五个UITabBarButton对象就会显示成”More”类型的按钮
。
二、UITabBarController的知识点
2.1 关于UITabBarController
UITabBarController没有根控制器的概念。
在添加了相同的子控制器,不会增加tabitem的数量
。子控器可以是UIViewController、UINavigationController、UITableViewController或者其他的视图控制器UITabBarButton在UITabBar中的位置是均分的,UITabBar的高度为49,UITabBarButton⾥面显⽰什么内容,由对应子控制器的tabBarItem属性来决定
UITabBarController一般作为应用程序的rootViewController,但是
它不能作为UINavigationController的根控制器
UITabBarController
默认只支持竖屏
,当设备方向放生变化时候,它会查询viewControllers属性中包含的所有ViewController,仅当所有的viewController都支持该方向时
,UITabBarController才会发生旋转,否则默认的竖向
2.2 关于UITabBar
2.2.1 简介
UITabBar继承于UIView,方便用户切换到对应的界面,当往标签控制器里添加子控制器,标签栏就会有序的自动生成对应的标签;创建一个标签控制器,就默认创建一个标签栏,标签栏最多显示5个标签
2.2.2 UITabBar常用的属性和方法
// 代理
@property(nonatomic,assign) id<UITabBarDelegate> delegate;
// 设置数据模型,不能给系统默认创建的UITabBar设置items
@property(nonatomic,copy) NSArray *items;
// 设置选中数据模型,不能给系统默认创建的UITabBar设置selectedItem
@property(nonatomic,assign) UITabBarItem *selectedItem;
// iOS7之前,tintColor可以修改背景色
@property(nonatomic,retain) UIColor *tintColor;
// iOS7之后,修改背景色只能用barTintColor
@property(nonatomic,retain) UIColor *barTintColor;
// 设置UITabBar的背景图片
@property(nonatomic,retain) UIImage *backgroundImage
// 设置选中的按钮的背景图片
@property(nonatomic,retain) UIImage *selectionIndicatorImage
// 设置阴影图片,但必须设置backgroundImage属性
@property(nonatomic,retain) UIImage *shadowImage
// 设置数据模型,不能给系统默认创建的UITabBar设置items
- (void)setItems:(NSArray *)items animated:(BOOL)animated;
代理方法:
// 选中时调用
- (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item;
// 即将编辑时调用
- (void)tabBar:(UITabBar *)tabBar willBeginCustomizingItems:(NSArray *)items;
// 编辑时调用
- (void)tabBar:(UITabBar *)tabBar didBeginCustomizingItems:(NSArray *)items;
// 即将结束编辑时调用
- (void)tabBar:(UITabBar *)tabBar willEndCustomizingItems:(NSArray *)items changed:(BOOL)changed;
// 结束编辑时调用
- (void)tabBar:(UITabBar *)tabBar didEndCustomizingItems:(NSArray *)items changed:(BOOL)changed;
2.2.3 UITabBarItem
---------- UITabBarItem的常用接口
@interface UITabBarItem : UIBarItem
// 设置选中图片
@property(nonatomic,retain) UIImage *selectedImage;
// 设置角标,一般用于提示用户有新消息
@property(nonatomic,copy) NSString *badgeValue;
// 初始化UITabBarItem对象
- (instancetype)initWithTitle:(NSString *)title image:(UIImage *)image tag:(NSInteger)tag;
// 初始化UITabBarItem对象
- (instancetype)initWithTitle:(NSString *)title image:(UIImage *)image selectedImage:(UIImage *)selectedImage;
// 初始化UITabBarItem对象
- (instancetype)initWithTabBarSystemItem:(UITabBarSystemItem)systemItem tag:(NSInteger)tag;
@end
---------- UIBarItem的常用接口
@interface UIBarItem : NSObject
// 是否有效
@property(nonatomic,getter=isEnabled) BOOL enabled;
// 设置标题
@property(nonatomic,copy) NSString *title;
// 设置图片
@property(nonatomic,retain) UIImage *image;
// 设置横向图片
@property(nonatomic,retain) UIImage *landscapeImagePhone;
// 设置图片边距
@property(nonatomic) UIEdgeInsets imageInsets;
// 设置横向图片边距
@property(nonatomic) UIEdgeInsets landscapeImagePhoneInsets;
// 设置对应的控制器的标签
@property(nonatomic) NSInteger tag;
@end
---------- UITabBarSystemItem的枚举类型
typedef NS_ENUM(NSInteger, UITabBarSystemItem) {
UITabBarSystemItemMore,
UITabBarSystemItemFavorites,
UITabBarSystemItemFeatured,
UITabBarSystemItemTopRated,
UITabBarSystemItemRecents,
UITabBarSystemItemContacts,
UITabBarSystemItemHistory,
UITabBarSystemItemBookmarks,
UITabBarSystemItemSearch,
UITabBarSystemItemDownloads,
UITabBarSystemItemMostRecent,
UITabBarSystemItemMostViewed,
};
2.2.4 覆盖UITabBarController自带的tabBar为自定义的tabBar操作原理
tabBar上的按钮是在viewDidAppear的时候拿到 self.tabBar 再调用addSubViews添加上去的,在viewDidAppear之前把控制器的tabBar换成我们自己的tabBar,就会把tabBar上的按钮添加到自己的tabBar上。但是tabBar控制器的tabBar属性是只读的,不能直接赋值,可以利用运行时机制发送消息
三、应用
-(void)RTSetUpSubVcs{
TGHomeViewController *HomeVC = [[TGHomeViewController alloc]init];
HomeVC.view.backgroundColor = [UIColor whiteColor];
BSENavigationController *HomeNav = [self ChildVC:HomeVC
WithTitle:@"今托管"
image:@"tabbar_search"
selectedImage:@"tabbar_search_sel"];
TGRootChildrenViewController *childrenVC = [TGRootChildrenViewController new];
BSENavigationController *childrenNav = [self ChildVC:childrenVC
WithTitle:@"小孩"
image:@"tabBar_children"
selectedImage:@"tabBar_children_sel"];
TGMineViewController *MyVC = [TGMineViewController new];
BSENavigationController *MyNav = [self ChildVC:MyVC
WithTitle:@"我的"
image:@"tabBar_mine"
selectedImage:@"tabBar_mine_sel"];
self.tabBar.barTintColor = [UIColor whiteColor];//tabbar 背景色
self.tabBar.translucent = NO;//tarbar非透明
self.viewControllers = @[HomeNav,childrenNav,MyNav];
}
#pragma mark - 根TabBarController 添加子视图
-(BSENavigationController *)ChildVC:(UIViewController *)VC WithTitle:(NSString *)title image:(NSString *)imagename selectedImage:(NSString *)selectedImageName
{
VC.title = title;
UITabBarItem *barItem = [[UITabBarItem alloc]init];
barItem.title = title;
barItem.image = [[UIImage imageNamed:imagename]imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
barItem.selectedImage = [[UIImage imageNamed:selectedImageName]imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
[barItem setTitleTextAttributes:@{NSForegroundColorAttributeName: HEXCOLOR(0x666666)} forState:UIControlStateNormal];
// 选中状态下的文字颜色
[barItem setTitleTextAttributes:@{NSForegroundColorAttributeName: HEXCOLOR(kBlueGrayColor)} forState:UIControlStateSelected];
BSENavigationController *Nav = [[BSENavigationController alloc]initWithRootViewController:VC];
Nav.tabBarItem = barItem;
return Nav;
}
四、遇到的问题
1.之前初始化写错了添加子控制器的方法,设置了子控制的backgroundColor 导致 tabbarcontroller初始化所有子控制进入了didload方法。这样的直接坏处就是多数子控制器在didload里面都有网络请求方法,并且接口都有登录权限设置,如果初始化都直接加载,在用户登录成功后所有控制器又要在登录成功后,重新加载一次网络请求。浪费性能,同时也增加了程序的复杂度。