UITabBarController 和 UINavigationController 几乎是iOS APP的标配。
UITabBarController分栏(标签栏)控制器, 和UINavigationController导航控制器一样,都是用来管理视图控制器的容器类型的控制器。
1、UITabBarController的基本使用
(1)、创建几个视图控制器
(2)、将视图控制器添加到TabBarController
(3)、设置窗口的跟视图控制器为分栏控制器
(4)、设置分栏控制器的显示样式
UIViewController *vc1 = [[UIViewController alloc] init];
vc1.view.backgroundColor = [UIColor redColor];
vc1.title = @"VC1";
// 视图控制器的分栏按钮
// 视图控制器的分栏按钮,如果没有被显示创建,并且被使用了,则会自动根据视图控制器的title来创建
//vc1.tabBarItem;
UIViewController *vc2 = [[UIViewController alloc] init];
vc2.view.backgroundColor = [UIColor yellowColor];
vc2.title = @"VC2";
UIViewController *vc3 = [[UIViewController alloc] init];
vc3.view.backgroundColor = [UIColor blueColor];
vc3.title = @"VC3";
UIViewController *vc4 = [[UIViewController alloc] init];
vc4.view.backgroundColor = [UIColor greenColor];
vc4.title = @"VC4";
// 创建分栏(标签栏)控制器, 和导航控制器一样,都是用来管理视图控制器的容器类型的控制器。
// 分栏控制器和导航控制器一样,也是通过viewControllers来管理其子视图控制器
UITabBarController *tabBarCtrl = [[UITabBarController alloc] init];
tabBarCtrl.view.backgroundColor = [UIColor cyanColor];
// 把数据中得视图器交给分栏控制器管理
// 分栏控制器会自动将其管理的视图控制器的分栏按钮(UITabBarItem)放到分栏上显示
tabBarCtrl.viewControllers = @[vc1, vc2, vc3, vc4];
// 设置窗口的跟视图控制器为分栏控制器
self.window.rootViewController = tabBarCtrl;
// 取到分栏控制器的分栏
UITabBar *tabBar = tabBarCtrl.tabBar;
// 设置分栏的风格
tabBar.barStyle = UIBarStyleBlack;
// 是否透明
tabBar.translucent = NO;
// 设置分栏的前景颜色
tabBar.barTintColor = [UIColor brownColor];
// 设置分栏元素项的颜色
tabBar.tintColor = [UIColor purpleColor];
// 设置分栏按钮的选中指定图片
tabBar.selectionIndicatorImage = [UIImage imageNamed:@"home.png"];
[self.window makeKeyAndVisible];
效果如图:
2、UITabBarController和的UINavigationController结合使用
如果有如图需求:点击切换到下一个页面,隐藏UITabBarController。
(1)、创建分栏控制器:
// 创建分栏控制器管理的子视图控制器
- (void)createViewControllers
{
OneViewController *oneVC = [[OneViewController alloc] init];
MyNavgationController *navCtrl1 = [[MyNavgationController alloc] initWithRootViewController:oneVC];
// navCtrl1.tabBarItem = [[UITabBarItem alloc] initWithTabBarSystemItem:UITabBarSystemItemSearch tag:0];
TwoViewController *twoVC = [[TwoViewController alloc] init];
UINavigationController *navCtrl2 = [[UINavigationController alloc] initWithRootViewController:twoVC];
ThreeViewController *threeVC = [[ThreeViewController alloc] init];
FourViewController *fourVC = [[FourViewController alloc] init];
FiveViewController *fiveVC = [[FiveViewController alloc] init];
SixViewController *sixVC = [[SixViewController alloc] init];
// 分栏控制器管理的视图控制器的tabBarController属性,自动指向分栏控制器。
// 当分栏控制器管理的视图控制器的个数超过五个时,会自动创建一个more的导航控制器,并且自动将第五个以及以后的视图控制器添加到more导航控制器中。
self.viewControllers = @[navCtrl1, navCtrl2, threeVC, fourVC, fiveVC, sixVC];
}
(2)、在MyNavgationController里面,重写跳转方法:
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
//1. 取出分栏
UITabBar *tabBar = self.tabBarController.tabBar;
// 将frame左移分栏的宽度
CGRect frame = tabBar.frame;
frame.origin.x -= tabBar.frame.size.width;
// 动画影藏tabBar
[UIView animateWithDuration:0.28 animations:^{
tabBar.frame = frame;
}];
[super pushViewController:viewController animated:animated];
}
- (UIViewController *)popViewControllerAnimated:(BOOL)animated
{
//1. 取出分栏
UITabBar *tabBar = self.tabBarController.tabBar;
// 将frame左移分栏的宽度
CGRect frame = tabBar.frame;
frame.origin.x += tabBar.frame.size.width;
// 动画影藏tabBar
[UIView animateWithDuration:0.28 animations:^{
tabBar.frame = frame;
}];
return [super popViewControllerAnimated:YES];
}
3、定制UITabBarController
#import "MyTabBar.h"
@interface MyTabBarController ()
// 保存之前选中的按钮
@property (nonatomic, retain) UIButton *preSelBtn;
@end
@implementation MyTabBarController
- (void)viewDidLoad {
[super viewDidLoad];
[self createViewControllers];
[self createTabBar];
}
// 创建分栏控制器管理的视图控制器数据
- (void)createViewControllers
{
FirstViewController *firstVC = [[FirstViewController alloc] init];
UINavigationController *nav1 =[[UINavigationController alloc] initWithRootViewController:firstVC];
SecondViewController *secondVC = [[SecondViewController alloc] init];
ThirdViewController *thirdVC = [[ThirdViewController alloc] init];
FourthViewController *fourthVC = [[FourthViewController alloc] init];
self.viewControllers = @[nav1, secondVC, thirdVC, fourthVC];
}
// 定制tabBar tabBar 49
- (void)createTabBar
{
// 0. 隐藏分栏控制器自带的tabbar
[self.tabBar setHidden:YES];
MyTabBar *tabBr = [[MyTabBar alloc] init];
tabBr.frame = self.tabBar.frame;
tabBr.delegate = self;
[self.view addSubview:tabBr];
}
#pragma mark - MyTabBarDelegate协议方法
- (void)tabBar:(MyTabBar *)tabBar didSelectItemWithIndex:(NSUInteger)toIndex
{
// 设置分栏控制器选中的视图控制器
self.selectedIndex = toIndex;
}
@class MyTabBar;
@protocol MyTabBarDelegate
@optional
- (void)tabBar:(MyTabBar *)tabBar didSelectItemWithIndex:(NSUInteger)toIndex;
- (void)tabBar:(MyTabBar *)tabBar didSelectItemWithIndex:(NSUInteger)toIndex fromIndex:(NSUInteger)fromIndex;
@end
@interface MyTabBar : UIImageView
@property (nonatomic, assign) id delegate;
@end
#import "MyTabBar.h"
#define TABBAR_BTN_START_TAG 100
#define BTN_COUNT 4
@interface TabBarButton : UIButton
@end
@implementation TabBarButton
// 重写高亮的方法。在这个方法中,我们忽略按钮的高亮状态
- (void)setHighlighted:(BOOL)highlighted
{
// NSLog(@"highlighted = %d", highlighted);
// [super setHighlighted:NO];
}
@end
@interface MyTabBar ()
// 保存分栏之前选中的按钮
@property (nonatomic, retain) TabBarButton *preSelBtn;
@end
@implementation MyTabBar
- (instancetype)init
{
if (self = [super init]) {
NSLog(@"init");
}
return self;
}
// init方法会调用initWithFrame ,给控件添加子控件在initWithFrame中添加
- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
// 1.2 设置背景视图的背景图片
self.image = [UIImage imageNamed:@"tabbg.png"];
// 1.3 设置用户交互属性可用(父控件不能与用户进行交互,则所有子控件都不能与用户交互)
self.userInteractionEnabled = YES;
// 2. 在分栏背景上添加按钮
for (int i = 0; i < BTN_COUNT; i++) {
TabBarButton *btn = [TabBarButton buttonWithType:UIButtonTypeCustom];
// 设置正常状态下的显示图片
NSString *imageName = [NSString stringWithFormat:@"tab_%d", i];
[btn setImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal];
// 设置按钮在选中状态下的显示图片
NSString *imageSelName = [NSString stringWithFormat:@"tab_c%d",i];
[btn setImage:[UIImage imageNamed:imageSelName] forState:UIControlStateSelected];
// 第一个按钮默认为选中
if (i == 0) {
btn.selected = YES;
self.preSelBtn = btn;
}
// 监听按钮的点击事件
[btn addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchDown];
btn.tag = TABBAR_BTN_START_TAG + i;
// 将按钮添加到背景视图上显示
[self addSubview:btn];
}
}
return self;
}
- (void)btnClick:(TabBarButton *)btn
{
// 1. 取消之前选中按钮的选中状态
self.preSelBtn.selected = NO;
// 2. 将当前点击的按钮设为选中状态
btn.selected = YES;
// 3. 保存当前选中的按钮
self.preSelBtn = btn;
// 如果代理实现了协议方法,通过协议方法通知代码当前控件上的第几个按钮被点击了。
if ([self.delegate respondsToSelector:@selector(tabBar:didSelectItemWithIndex:)]) {
[self.delegate tabBar:self didSelectItemWithIndex:btn.tag - TABBAR_BTN_START_TAG];
}
}
// 这个方法在控件的frame(大小)修改后被调用
- (void)layoutSubviews
{
// 这行代码不能少
[super layoutSubviews];
// 取出子控件的个数
NSUInteger count = self.subviews.count;
// 调整子控件的大小
CGFloat btnY = 0;
CGFloat btnW = self.bounds.size.width / count;
CGFloat btnH = self.bounds.size.height;
int i = 0;
// 取出所有的子控件,调整frame
for (TabBarButton *btn in self.subviews) {
// 设置frame
CGFloat btnX = btnW * i;
btn.frame = CGRectMake(btnX, btnY, btnW, btnH);
i++;
}
}
效果如图: