首先说明一下为什么要自定义TabBar
默认TabBar有图片和文字,如果素材是图文分开的,那么一般不再需要自定义TabBar,如果素材是图文一起的,不设置文字,只设置了TabBar的图片,那么实现的效果就会片上方,留出文字的空白部分,如图:
所以这种情况下一般需要自定义TabBar:
还有不同IOS下,TabBar的样式存在差别,如IOS6的拟物化,IOS7开始扁平化,如果需要支持多版本,同时达到样式一致,也可以通过自定义的方式实现(这种情况可能不会遇到,一般只要保证支持三个大版本就可以了)
先创建一个类,继承自UIView
@class JSTabBarView;
@protocol TabBarViewSelectedIndexDelegate <NSObject>
//View中添加Button实现点击,此时还无法切换控制器,所以这里用到了代理,在创建Button的时候,设置Tag值,通过代理将Tag值回传,再通过TabBar控制器的selectedIndex属性切换控制器
- (void)tabBarView:(JSTabBarView *)tabBarView withSelectedJSButtonTag:(JSButton *)button;
@end
@interface JSTabBarView : UIView
@property (nonatomic,weak) id <TabBarViewSelectedIndexDelegate> delegate;
/**
* 创建自定义TabBar中Button的图片
*
* @param imageNormal UIControlStateNormal状态下的图片
* @param imageSel UIControlStateSelected状态下的图片
*/
- (void)creatButtonWithNormalImage:(NSString *)normalImageName andSelectdImage:(NSString *)selectedImageName;
@end
.m文件中
@interface JSTabBarView ()
//JSButton继承自UIButton,里面只是重写了setHighlighted:(BOOL)highlighted,去掉系统默认提供的样式(点击button时高亮显示)
@property (nonatomic,strong) JSButton *selectedButton;
@end
@implementation JSTabBarView
- (void)creatButtonWithNormalImage:(NSString *)normalImageName andSelectdImage:(NSString *)selectedImageName{
UIImage *normalImage = [UIImage imageNamed:normalImageName];
UIImage *selectedImage = [UIImage imageNamed:selectedImageName];
JSButton *button = [[JSButton alloc]init];
[button setImage:normalImage forState:UIControlStateNormal];
[button setImage:selectedImage forState:UIControlStateSelected];
[self addSubview:button];
[button addTarget:self action:@selector(buttonClick:) forControlEvents:UIControlEventTouchDown];
}
/**
* 按钮的点击事件中主要有两部分:
* 1.点中当前button时取消上一个button的选中状态
* 2.代理对象执行代理方法
*/
- (void)buttonClick:(JSButton *)sender{
self.selectedButton.selected = NO;
sender.selected = YES;
self.selectedButton = sender;
if ( [self.delegate respondsToSelector:@selector(tabBarView:withSelectedJSButtonTag:)]) {
[self.delegate tabBarView:self withSelectedJSButtonTag:sender];
}
}
- (void)layoutSubviews{
[super layoutSubviews];
CGFloat width = self.bounds.size.width / self.subviews.count;
CGFloat heigth = self.bounds.size.height;
CGFloat buttonY = 0;
for (int i = 0; i < self.subviews.count; i ++) {
CGFloat buttonX = i * width;
JSButton *button = (JSButton *)self.subviews[i];
button.tag = i;
button.frame = CGRectMake(buttonX, buttonY, width, heigth);
if (i == 0) {
[self buttonClick:button];
}
}
}
这样自定义的TabBar就可以导入使用了,先创建一个继承自TabBarController的类,创建一个自定义的TabBarView,并将TabBarView添加到当前自定义TabBarController的tabBar上,for循环创建自定义TabBar上的button,实现代理方法切换选中Button对应的控制器
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
/**
* 获取导航控制器
*/
UINavigationController *hallNavigationController = [self loadStoryBoardWithStoryBoardName:@"Hall"];
UINavigationController *arenalNavigationController = [self loadStoryBoardWithStoryBoardName:@"Arenal"];
UINavigationController *discoveryNavigationController = [self loadStoryBoardWithStoryBoardName:@"Discovery"];
UINavigationController *historyNavigationController = [self loadStoryBoardWithStoryBoardName:@"History"];
UINavigationController *myLotteryNavigationController = [self loadStoryBoardWithStoryBoardName:@"MyLottery"];
//给当前的自定义TabBarController设置子控制器
self.viewControllers = @[hallNavigationController,arenalNavigationController,discoveryNavigationController,historyNavigationController,myLotteryNavigationController];
//创建自定义的TabBarView
JSTabBarView *tabBarView = [[JSTabBarView alloc]init];
//设置代理对象
tabBarView.delegate = self;
// tabBarView.frame = self.tabBar.frame;
// [self.view addSubview:tabBarView];//如果按这种方式设置frame和添加到视图,当push到某一控制器后需要隐藏TabBar时,自定义的TabBarView还存在(所以需要通过设置bounds,并添加到tabBar上)
//设置frame
tabBarView.frame = self.tabBar.bounds;
//将自定义的TabBarView添加到当前自定义TabBarController的tabBar上(将tabBar覆盖)
[self.tabBar addSubview:tabBarView];
//for循环创建自定义TabBarView中的button(根据子控制器的个数创建)
for (int i = 0; i < self.viewControllers.count; i ++) {
[tabBarView creatButtonWithNormalImage:[NSString stringWithFormat:@"TabBar%d",i+1] andSelectdImage:[NSString stringWithFormat:@"TabBar%dSel",i+1]];
}
}
代理方法:
/**
* 自定义TabBarView的代理方法,实现控制器切换
*
* @param tabBarView 自定义的TabBarView
* @param button 选中的Button
*/
- (void)tabBarView:(JSTabBarView *)tabBarView withSelectedJSButtonTag:(JSButton *)button{
//这里利用TabBarController的selectedIndex属性通过传递的button的tag值来进行设置,实现控制器的切换
self.selectedIndex = button.tag;
}