网上实现自定义UITabBarController
的文章多如牛毛,实现的方法也大同小异。关键是如何实现一个客制化的UITabBar
,去除默认生成的UITabBarButton
。
较普遍的做法是,在UITabBarController
的viewWillLayoutSubviews
方法中遍历tabBar
的子视图,将其中的UITabBarButton
一一去除。
- (void)viewWillLayoutSubviews {
[super viewWillLayoutSubviews];
for (UIView *child in self.tabBar.subviews) {
if ([child isKindOfClass:NSClassFromString(@"UITabBarButton")]) {
[child removeFromSuperview];
}
}
}
这样做的问题有两个:
- 效率低下,不作限制的话
UITabBarController
生命周期内还会多次调用 - 当
UITabBarController
的子视图控制器有设置title
等属性时,还会在切换视图页面出现重新添加UITabBarButton
的诡异情况
这种情况猜测是UITabBarController
在改变selectedIndex
的同时,会刷新UITabBar
的UITabBarItem
列表items
,同时根据items
进行刷新布局。既然有了大概猜想,解决方案自然随之而生:将items
置空,并阻止添加就好了。
// CYTabBar.h
#import <UIKit/UIKit.h>
@interface CYTabBar : UITabBar
@end
@implementation CYTabBar
- (NSArray<UITabBarItem *> *)items {
return @[];
}
// 重写,空实现
- (void)setItems:(NSArray<UITabBarItem *> *)items {
}
- (void)setItems:(NSArray<UITabBarItem *> *)items animated:(BOOL)animated {
}
@end
再靠KVC把UITabBarController
中的tabBar
替换掉。
// UITabBarController子类
CYTabBar *cyTabBar = [[CYTabBar alloc] init];
cyTabBar.frame = self.tabBar.bounds;
[self setValue: cyTabBar forKey:@"tabBar"];
大功告成,可以在自己的tabBar中为所欲为了!
最后还有点友情提示,尽量不要以UITabBarController
作为UINavigationController
的根视图控制器。该情况下UITabBarController
切换子页面时会产生视图控制器视图高度不对的问题,公用的NavigationBar也将变得难以控制。
//Don't do this
UIViewController *ctrl1 = [[UIViewController alloc] init];
UIViewController *ctrl2 = [[UIViewController alloc] init];
UIViewController *ctrl3 = [[UIViewController alloc] init];
UITabBarController *ctrl = [[UITabBarController alloc] init];
[ctrl setViewControllers:@[ctrl1, ctrl2, ctrl3] animated:NO];
UINavigationController *navCtrl =[[UINavigationController alloc] initWithRootViewController: ctrl];
[self presentViewController:navCtrl animated:YES completion:nil];
// Do this
UIViewController *ctrl1 = [[UIViewController alloc] init];
UINavigationController *navCtrl1 =[[UINavigationController alloc] initWithRootViewController: ctrl1];
UIViewController *ctrl2 = [[UIViewController alloc] init];
UINavigationController *navCtrl2 =[[UINavigationController alloc] initWithRootViewController: ctrl2];
UIViewController *ctrl3 = [[UIViewController alloc] init];
UINavigationController *navCtrl3 =[[UINavigationController alloc] initWithRootViewController: ctrl3];
UITabBarController *ctrl = [[UITabBarController alloc] init];
[ctrl setViewControllers:@[navCtrl1, navCtrl2, navCtrl3] animated:NO];
[self presentViewController:ctrl animated:YES completion:nil];
最后的最后再推荐一个TabBarController的开源库,在学习源码的过程中让我获益匪浅:ChenYilong/CYLTabBarController。
讲完,以上。