网上实现自定义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。
讲完,以上。













网友评论