和UINavigationController類似,UITabBarController也可以輕松地管理多個控制器,輕松完成控制器之間的切換。
UITabBarController的視圖結構如下芹扭;
-
UITabBar
下方的工具條稱為UITabBar 麻顶,如果UITabBarController有N個子控制器,那么UITabBar內(nèi)部就會有N 個UITabBarButton作為子控件與之對應。
注意:UITabBarButton在UITabBar中得位置是均分的冯勉,UITabBar的高度為49澈蚌。
在上面的程序中摹芙,UITabBarController有4個子控制器,所以UITabBar中有4個UITabBarButton灼狰,UITabBar的結構?大致如下圖所示:
-
UITabBarButton
UITabBarButton?面顯?什么內(nèi)容,由對應子控制器的tabBarItem屬性來決定
c1.tabBarItem.title=@"消息"; c1.tabBarItem.image=[UIImage imageNamed:@"tab_recent_nor"];
-
有兩種方式可以往UITabBarController中添加子控制器
(1)[tb addChildViewController:c1];
(2)tb.viewControllers=@[c1,c2,c3,c4]; selectedIndex屬性
通過該屬性可以獲得當前選中的viewController 的下標,以及手動切換子視圖浮禾。selectedViewController屬性
通過該屬性可以獲得當前選中的viewController交胚,一般直接獲得是 UINavigationController份汗。
每個視圖控制器都有一個tabBarController屬性,通過它可以訪問所在的UITabBarController
每個視圖控制器都有一個tabBarItem屬性蝴簇,通過它控制視圖在UITabBarController的tabBar中的顯示信息杯活。
系統(tǒng)自帶的TabBar
UITabBarController 中:
ViewController *vc1=[[ViewController alloc] init];
vc1.tabBarItem.title=@"首頁";
vc1.tabBarItem.image=[[UIImage imageNamed:@"111N"]
imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
vc1.tabBarItem.selectedImage=[[UIImage imageNamed:@"111L"]
imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
BHHHViewController *vc2=[[BHHHViewController alloc] init];
vc2.tabBarItem.title=@"排行";
vc2.tabBarItem.image=[[UIImage imageNamed:@"222N"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
vc2.tabBarItem.selectedImage=[[UIImage imageNamed:@"222L"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
UINavigationController *nav1=[[UINavigationController alloc] initWithRootViewController:vc1];
UINavigationController *nav2=[[UINavigationController alloc] initWithRootViewController:vc2];
self.viewControllers=@[nav1,nav2];
設置TabBar背景顏色
tabBar和navigationBar 設置這個線的顏色都是使用 setShadowImage 這個方法.
方法-:
self.tabBar.barTintColor = [UIColor blueColor];;//這樣是也可以修改顏色
方法二:
UIView *backView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, WIDTH, Scale_Y(49))];
backView.backgroundColor = RGB(248, 150, 68, 1);
[self.tabBar insertSubview:backView atIndex:0];
self.tabBar.opaque = YES;
設置TabBar頂部細線的顏色
UIImageView *navBarHairlineImageView = [[MethodTool shareTool] findHairlineImageViewUnder:self.tabBar];
navBarHairlineImageView.hidden = YES;
//設置背景顏色或圖片
[self.tabBar setBackgroundImage:[[MethodTool shareTool]imageWithColor:[UIColor whiteColor] size:CGSizeMake(WIDTH, 49)]];
//設置頂部細線的顏色
[self.tabBar setShadowImage:[[MethodTool shareTool]imageWithColor:ViewlineColor size:CGSizeMake(WIDTH, 0.5)]];
//設置點擊后的選中 item 背景顏色
[self.tabBar setSelectionIndicatorImage:[[MethodTool shareTool]imageWithColor:[UIColor redColor] size:CGSizeMake(WIDTH/3, 49)]];
//*********************************
- (UIImageView *)findHairlineImageViewUnder:(UIView *)view {
if ([view isKindOfClass:UIImageView.class] && view.bounds.size.height <= 1.0) {
return (UIImageView *)view;
}
for (UIView *subview in view.subviews) {
UIImageView *imageView = [self findHairlineImageViewUnder:subview];
if (imageView) {
return imageView;
}
}
return nil;
}
設置TabBar下面的字體在不同狀態(tài)下的顏色:
[[UITabBarItem appearance] setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[UIColor blackColor], NSForegroundColorAttributeName, nil] forState:UIControlStateNormal];
[[UITabBarItem appearance] setTitleTextAttributes: [NSDictionary dictionaryWithObjectsAndKeys:[UIColor redColor] ,NSForegroundColorAttributeName, nil]forState:UIControlStateSelected];
NSForegroundColorAttributeName 是iOS7.0之后才使用的,之前是 UITextAttributeTextColor熬词,關于棄用后如何找到一個替代者旁钧,其實很簡單,認真閱讀:
系統(tǒng)自帶的TabBar 中關于底部Bar的隱藏問題和返回展現(xiàn)的最簡單的方法:
1. 在 BaseViewController 里面的 ViewDidLoad里面設置
if (self.navigationController.viewControllers.count>1) {
self.hidesBottomBarWhenPushed = YES;
}
//如果在push跳轉(zhuǎn)時需要隱藏tabBar互拾,需要在最外層的VC中跳轉(zhuǎn)之前設置
// block 回調(diào)中跳轉(zhuǎn) 需要緊緊寫在跳轉(zhuǎn)的前后
self.hidesBottomBarWhenPushed=YES;
NextViewController *next=[[NextViewController alloc]init];
[self.navigationController pushViewController:next animated:YES];
self.hidesBottomBarWhenPushed=NO;
//這樣back回來的時候歪今,tabBar會恢復正常顯示。
2. 只需在第一層頁面向第二層頁面跳轉(zhuǎn)的地方設置一次即可颜矿,第二層向第三層跳轉(zhuǎn)時不需要再次設置寄猩,當然,想在第三層頁面上顯示出 tabbar骑疆,設置.hidesBottomBarWhenPushed = NO也是不可能的出效果的田篇。
NextViewController *next=[[NextViewController alloc]init];
next.hidesBottomBarWhenPushed = YES;
[self.navigationController pushViewController:next animated:YES];
3.在 BaseViewController 里面的 init方法里面設置如下:也可以達到特定頁面隱藏 tabbar 的效果。(只要在 push前設定 nextView 的hidesBottomBarWhenPushed屬性才可以有效果箍铭,在 push 方法之后的設置都不行泊柬,init 方法在 push 方法之前執(zhí)行)
if ([NSStringFromClass(self.class) isEqualToString:@"IndexViewController"]||[NSStringFromClass(self.class) isEqualToString:@"MedicalViewController"]) {
self.hidesBottomBarWhenPushed = NO;
}else{
self.hidesBottomBarWhenPushed = YES;
}
4. for in 的方法找到 UITabbar ,手動隱藏和展現(xiàn)坡疼,效果圖如下:
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self hideTabBar];
}
-(void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[self showTabBar];
}
-(void)hideTabBar{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
for(UIView *view in self.tabBarController.view.subviews)
{
if([view isKindOfClass:[UITabBar class]])
{
[view setFrame:CGRectMake(view.frame.origin.x, HEIGHT, view.frame.size.width, view.frame.size.height)];
}else
{
[view setFrame:CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, 480)];
}
}
[UIView commitAnimations];
}
-(void)showTabBar {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
for(UIView *view in self.tabBarController.view.subviews)
{
NSLog(@"%@",view);
if([view isKindOfClass:[UITabBar class]])
{
[view setFrame:CGRectMake(view.frame.origin.x, HEIGHT-49, view.frame.size.width, view.frame.size.height)];
view.hidden = NO;
}else
{
[view setFrame:CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, 431)];
}
}
[UIView commitAnimations];
}
關于隱藏底部的Tabbar 推薦使用第二種方法彬呻,最方便快捷。
自定義TbarBar 視圖切換時的動畫的關鍵方法(后續(xù)會整理出視圖切換時的動畫實現(xiàn))
- (id <UIViewControllerAnimatedTransitioning>)tabBarController:(UITabBarController *)tabBarController
animationControllerForTransitionFromViewController:(UIViewController *)fromVC
toViewController:(UIViewController *)toVC NS_AVAILABLE_IOS(7_0);
{
return ani;
}
其他相同的用法還有很多:
<UINavigationControllerDelegate>
- (nullable id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
animationControllerForOperation:(UINavigationControllerOperation)operation
fromViewController:(UIViewController *)fromVC
toViewController:(UIViewController *)toVC
{ if(operation==UINavigationControllerOperationPush)
{ if(fromVC==self)
{
return ani;
} }
return nil;
}
這里的ani 是一個遵從<UIViewControllerAnimatedTransitioning>的類對象柄瑰。
UIAppearance是一個協(xié)議闸氮,UIView默認已經(jīng)遵守了這個協(xié)議。
@protocol UIAppearance <NSObject>
UIView 默認遵從 UIAppearance 協(xié)議
讓某一類控件在另一種控件中同時變現(xiàn)某種屬性
[[UIButton appearanceWhenContainedInInstancesOfClasses:@[[UIView class]]] setTitleColor:[UIColor grayColor] forState:UIControlStateNormal];
上面這句話的意思 就是—-使UIView上面的UIButton的titleColor都變成灰色教沾,
而且作用域是整個工程, 也就是說蒲跨,不管在工程中的哪個位置寫下這句代碼,
整個工程中的按鈕的字體顏色都會變成灰色**
Tbbar 點擊時圖標加動畫
注意授翻,UITabbarViewController中已經(jīng)實現(xiàn)了 UITabBarDelegate或悲,如果再次設置 self.tabbar.delegate = self;會造成程序崩潰堪唐,并且 UITabbarViewController中 tabbar 是一個 只讀的屬性巡语,不能再次操作。
//會被自動調(diào)用
-(void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item{
NSInteger index = [self.tabBar.items indexOfObject:item];
[self animationWithIndex:index];
if([item.title isEqualToString:@"發(fā)現(xiàn)"])
{
}
}
- (void)animationWithIndex:(NSInteger) index {
NSMutableArray * tabbarbuttonArray = [NSMutableArray array];
for (UIView *tabBarButton in self.tabBar.subviews) {
if ([tabBarButton isKindOfClass:NSClassFromString(@"UITabBarButton")]) {
[tabbarbuttonArray addObject:tabBarButton];
}
}
CABasicAnimation*pulse = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
pulse.timingFunction= [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
pulse.duration = 0.08;
pulse.repeatCount= 1;
pulse.autoreverses= YES;
pulse.fromValue= [NSNumber numberWithFloat:0.7];
pulse.toValue= [NSNumber numberWithFloat:1.3];
[[tabbarbuttonArray[index] layer]
addAnimation:pulse forKey:nil];
}