现在的项目基本都是基于TabbarController + ViewControllers 来进行底层搭建的,如何更好的控制Tabbar的隐藏和显示就是一个需要面临的问题。
常做的做法有两种
- 在ViewWillAppear或者ViewWillDisappear中来控制。
- 设置viewController的hidesBottomBarWhenPushed为YES。
- 重写BaseNavigationController的pushViewController方法。
ViewWillAppear或者ViewWillDisappear中来控制
这种做法通常是在BaseViewController中,手动来控制tabbar的隐藏和显示。根据当前控制器的viewControllers来判断是隐藏还是显示。
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
if (self.navigationController.viewControllers.count > 1) {
self.tabBarController.tabBar.hidden = YES;
} else {
self.tabBarController.tabBar.hidden = NO;
}
}
这种做法可以暂时的解决问题,但是碰到UIToolBar和UITabbar同时使用时就会有问题。当Tabbar隐藏时,Toolbar的位置不会紧挨着底部。所以这时就需要采用做法2。
设置viewController的hidesBottomBarWhenPushed为YES。
这里通常存在一个疑问,到底是将谁的hidesBottomBarWhenPushed设置为YES。以ViewControllerA push ViewControllerB为例。
// 在ViewControllerA中调用此方法。
// 注意:这是一个错误的示范。
- (void)testPush {
ViewControllerB *vc = [[ViewControllerB alloc] init];
self.hidesBottomBarWhenPushed = YES;
[self.navigationController pushViewController:vc animated:YES];
}
当采用testPush这种方式进行push时,你会发现进入B页面时,可以正常的隐藏了Tabbar,但是当你从B页面pop回A页面时,你会发现Tabbar没有被正常的显示出来。 这是因为你当你调用self.hidesBottomBarWhenPushed = YES;
时,self是ViewControllerA,所以当你退回时也无法显示Tabbar。
正确的写法如下:
// 将B页面的hidesBottomBarWhenPushed设置成YES,才是正确的做法。
- (void)testPush2 {
ViewControllerB *vc = [[ViewControllerB alloc] init];
vc.hidesBottomBarWhenPushed = YES;
[self.navigationController pushViewController:vc animated:YES];
}
重写BaseNavigationController的pushViewController方法
身为一个程序员,你肯定不想每一处的push都写加一行这样的代码,又不能在BaseViewController里将hidesBottomBarWhenPushed的初始值设置成YES(因为Tabbar的rootViewControllers里的ViewController不可以设置这个值)。
比起Swizzling的方式来处理这个问题,重建一个BaseNavigationController并且重写- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
方法会更简单。
我最初的写法如下:
// 注意:这是个错误的写法
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated {
viewController.hidesBottomBarWhenPushed = YES;
[super pushViewController:viewController animated:animated];
}
一切看起来都没问题,当push页面时,才会将被push的页面的hidesBottomBarWhenPushed设置为YES。但是实际效果却是Tabbar.rootViewControllers里的viewController的hidesBottomBarWhenPushed也被设置成YES。
原因:
虽然我在代码中没有主动push过这些rootViewController,但是当调用[[BaseNavigationController alloc] initWithRootViewController:vc];
时,系统会自动调用BaseNavigationController的pushViewController方法。
所以我们需要将上面的方法修改成:
// 注意:这是个正确的写法
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated {
if (self.viewControllers.count > 0) {
viewController.hidesBottomBarWhenPushed = YES;
}
[super pushViewController:viewController animated:animated];
}