最近在写一个需求,自定义TabBar,自定义TabBar一般有两种方式:
- ① 创建一个类继承系统的UITabBar,在layoutSubviews方法中重新调整按钮的位置,再通过[self setValue:tabBar forKeyPath:@"tabBar"]方法,利用KVC设置TabBar,但是iOS 13后苹果粑粑不鼓励使用KVC;
- ② 创建一个继承UIView的类YBTabBar,然后把系统UITabBar上的UITabBarItem移除,然后把YBTabBar加到系统TabBar的位置上;
鉴于第二种继承UIView的方式更灵活且我们的tabbar还有一种类似漂浮的效果,所以这里我选用的是第二种方式,效果如下所示:
一、TabBar实现
其实就是自定义个UIView,然后布局5个按钮,核心代码如下所示:
- (void)addTabBarButtonNorImageUrl:(NSString *)norImageUrl
selImageUrl:(NSString *)selImageUrl
title:(NSString *)title {
// 1.创建按钮
YBTabBarButton *tabBarBtn = [[YBTabBarButton alloc] init];
tabBarBtn.delegate = self;
[self addSubview:tabBarBtn];
// 2.设置数据
[tabBarBtn setTabBarImageUrl:norImageUrl title:title];
// 3.监听按钮点击
[tabBarBtn addTarget:self action:@selector(buttonClick:) forControlEvents:UIControlEventTouchDown];
// 4.将自定义的YBTabBarButton对象
[self.tabbarBtnArray addObject:tabBarBtn];
[self.norImageArrM addObject:norImageUrl];
[self.selImageArrM addObject:selImageUrl];
// 5.默认选中第0个按钮
if (self.tabbarBtnArray.count == 1) {
[self buttonClick:tabBarBtn];
[tabBarBtn.iconBtn setSelected:YES];
}
}
- (void)layoutSubviews {
[super layoutSubviews];
// 按钮的frame数据
CGFloat buttonH = self.frame.size.height;
CGFloat buttonW = self.frame.size.width / self.tabbarBtnArray.count;
CGFloat buttonY = 0;
for (int index = 0; index < self.tabbarBtnArray.count; index++) {
// 1.取出按钮
YBTabBarButton *button = self.tabbarBtnArray[index];
// 2.设置按钮的frame
CGFloat buttonX = index * buttonW;
button.frame = CGRectMake(buttonX, buttonY, buttonW, buttonH);
// 3.绑定tag
button.tag = index;
}
}
二、再自定义一个继承系统的UITabBarController,
将系统的UITabBarItem移除,防止重影,然后将自定义UIView加到UITabBar。核心代码如下所示:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
// 初始化tabbar
[self setupTabbar];
// 初始化所有的子控制器
[self setupAllChildViewControllers];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
// 删除系统自动生成的UITabBarButton
for (UIView *child in self.tabBar.subviews) {
if ([child isKindOfClass:[UIControl class]]) {
[child removeFromSuperview];
}
}
}
- (void)setupTabbar {
//配置信息
YBConfig *config = [YBConfig shareInstance];
//config.titleFont = 12;
//config.norTitleColor = [UIColor blackColor];
//config.selTitleColor = [UIColor cyanColor];
//config.titleOffset = 5;
//config.imageOffset = 10;
//config.imageSize = CGSizeMake(50, 50);
//config.titleHeight = 12;
//config.bgImageOffset = 20;
YBTabBar *customTabBar = [[YBTabBar alloc] initWithFrame:self.tabBar.bounds config:config];
customTabBar.backgroundColor = [UIColor clearColor];
CGRect mainFrame = customTabBar.frame;
mainFrame.size.height = 88;
customTabBar.frame = mainFrame;
customTabBar.delegate = self;
[self.tabBar addSubview:customTabBar];
[customTabBar bringSubviewToFront:self.tabBar];
self.customTabBar = customTabBar;
}
/**
* 监听tabbar按钮的改变
* @param from 原来选中的位置
* @param to 最新选中的位置
*/
- (void)ybTabBar:(YBTabBar *)tabBar didSelectedButtonFrom:(NSInteger)from to:(NSInteger)to {
self.selectedIndex = to;
NSLog(@"----from:%ld, to:%ld ",from,to);
}
- (void)setupAllChildViewControllers {
// 1.首页
UIViewController *home = [[UIViewController alloc] init];
home.view.backgroundColor = [UIColor redColor];
[self setupChildViewController:home title:@"首页" imageName:@"shouye" selectedImageName:@"shouye_s"];
// 2.消息
UIViewController *message = [[UIViewController alloc] init];
message.view.backgroundColor = [UIColor orangeColor];
[self setupChildViewController:message title:@"消息" imageName:@"quanzi" selectedImageName:@"quanzi_s"];
// 3.首页
UIViewController *home1 = [[UIViewController alloc] init];
home1.view.backgroundColor = [UIColor blueColor];
[self setupChildViewController:home1 title:@"发现" imageName:@"shouye" selectedImageName:@"shouye_s"];
// 4.消息
UIViewController *message1 = [[UIViewController alloc] init];
message1.view.backgroundColor = [UIColor greenColor];
[self setupChildViewController:message1 title:@"广场" imageName:@"quanzi" selectedImageName:@"quanzi_s"];
}
/**
* 初始化一个子控制器
*
* @param childVc 需要初始化的子控制器
* @param title 标题
* @param imageName 图标
* @param selectedImageName 选中的图标
*/
- (void)setupChildViewController:(UIViewController *)childVc title:(NSString *)title imageName:(NSString *)imageName selectedImageName:(NSString *)selectedImageName {
// 1.设置控制器的属性
childVc.title = title;
// 设置图标
childVc.tabBarItem.image = [UIImage imageNamed:imageName];
// 设置选中的图标
UIImage *selectedImage = [UIImage imageNamed:selectedImageName];
childVc.tabBarItem.selectedImage = [selectedImage imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
childVc.tabBarItem.selectedImage = selectedImage;
// 2.包装一个导航控制器
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:childVc];
[self addChildViewController:nav];
// 3.添加tabbar内部的按钮
[self.customTabBar addTabBarButtonNorImageUrl:imageName
selImageUrl:selectedImageName
title:title];
}