 
 
在实际开发过程中,经常会发现系统自带的UITabBarViewController满足不了项目需求。
这时候,就需要自定义一个满足需求的UITabBarViewController了。
一、command + n
- 想要自定义UITabBarViewController,需要先创建一个继承于系统UITabBarViewController的类文件。
- 通常情况下,我们还需要自定义UITabBarViewController上的那个tabBar - [往往是重点],继承于UIView即可。
- 如: 
@interface JHTabBarViewController : UITabBarController
@interface JHTabBar : UIView        
二、设置回调
- 当我们点击某个tabBar时,需要用到回调来描述我们点击的究竟是什么,需要有什么样的效果。 
- 代理 
@class JHTabBar;//2
//1、协议
@protocol JHTabBarDelegate <NSObject>
//3、协议方法
- (void)tabBar:(JHTabBar *)tabBar clickBtn:(NSUInteger) index;
@end
@interface JHTabBar : UIView
//4、设置代理
@property(nonatomic, weak) id<JHTabBarDelegate> delegate;
@end         
此时,只是用普通的index来代表我们的tabBar,为了使其更具意义,定义成枚举:      
//5、定义枚举
typedef NS_ENUM(NSUInteger, JHItemType) {
    JHItemTypeMiddle,
    JHItemTypeLeft=100,//左边的item[具体意义自定]
    JHItemTypeRight
};
//再将index类型换为枚举类型
- (void)tabBar:(JHTabBar *)tabBar clickBtn:(JHItemType) index;        
- block
根据之前的分析可知,参数为JHTabBar类型的tabBar与JHItemType类型的index。     
typedef void(^TabBlock)(JHTabBar * tabBar,JHItemType index);
//7、block修饰使用copy
@property (nonatomic, copy)TabBlock block;    
三、创建item
先前我们已经定义好了代理和block,接下来设置item。
- 先设置item的数据源
/** item数据源 */
@property (nonatomic, strong)NSArray * itemsList; 
-(NSArray *)itemsList{
    if (!_itemsList) {
        _itemsList = @[@"tab_left",@"tab_right"];
    }
    return _itemsList;
}     
- 有了item的数据源,就可以进行item的初始化了[itemsList里放的是tabBar未被选中时的图片名称]
//view中、控件初始化
-(instancetype)initWithFrame:(CGRect)frame{
    self = [super initWithFrame:frame];
    if (self) {
        for (NSInteger i=0; i<self.itemsList.count; i++) {
            UIButton *item = [UIButton buttonWithType:UIButtonTypeCustom];
            [item setImage:[UIImage imageNamed:self.itemsList[i]] forState:UIControlStateNormal];
            [item setImage:[UIImage imageNamed:[self.itemsList[i] stringByAppendingString:@"_p"]] forState:UIControlStateSelected];
            [item addTarget:self action:@selector(clickItem:) forControlEvents:UIControlEventTouchUpInside];
            item.tag = JHItemTypeLeft + I;
           //图片取消高亮
            item.adjustsImageWhenHighlighted = NO;
            [self addSubview:item];
        }
    }
    return self;
}     
- 计算frame
-(void)layoutSubviews{
    [super layoutSubviews];
    CGFloat w = self.bounds.size.width / self.itemsList.count;
    for (NSInteger i=0; i< [self subviews].count; i++) {
        UIView * btn = [self subviews][I];
        if ([btn isKindOfClass:[UIButton class]]) {
            btn.frame = CGRectMake((btn.tag - JHItemTypeLeft)*w, 0, w, self.frame.size.height);
        }
    }
}     
- 响应方法
- (void)clickItem:(UIButton *)button{
    //判断代理是否能响应某个方法
    if ([self.delegate respondsToSelector:@selector(tabBar:clickBtn:)]) {
        [self.delegate tabBar:self clickBtn:button.tag];
    }
    //走block
    //!self.block?:self.block(self,button.tag)
    if (self.block) {
        self.block(self, button.tag);
    }
}     
四、创建tabBar
tanBar内部的定义先告一段落,现在在JHTabBarViewController里定义一个tabBar
- 导入头文件
#import "JHTabBar.h"     
- 创建自定义的tabBar
@property (nonatomic, strong)JHTabBar * jhTabBar;     
- 设置代理
@interface JHTabBarViewController ()<JHTabBarDelegate>     
- 懒加载
-(JHTabBar *)jhTabBar{
    if (!_jhTabBar) {
        _jhTabBar = [[JHTabBar alloc]initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, 49)];
        _jhTabBar.delegate = self;
    }
    return _jhTabBar;
}     
- 加载控制器
[self setupChildrenViewController];
- (void)setupChildrenViewController{
    NSMutableArray * childArr = [NSMutableArray arrayWithArray:@[@"leftVC",@"rightVC"]];
    for (NSInteger i=0; i<childArr.count; i++) {
        NSString *vcName = childArr[I];
        UIViewController *vc = [[NSClassFromString(vcName) alloc]init];
        JHNavigationController * nav = [[JHNavigationController alloc]initWithRootViewController:vc];
        [childArr replaceObjectAtIndex:i withObject:nav];
    }
    self.viewControllers = childArr;
}     
- 加载tabBar
[self.tabBar addSubview:self.jhTabBar];     
- 实现代理方法
#pragma mark ---- 实现JHTabBarDelegate方法
-(void)tabBar:(JHTabBar *)tabBar clickBtn:(JHItemType)index{
    self.selectedIndex = index - JHItemTypeLeft;
}     
五、添加lastItem
- 在JHTabBar里
/** 上一次点击的item */
@property (nonatomic, strong) UIButton * lastItem;     
- 在- (instancetype)initWithFrame:(CGRect)frame NS_DESIGNATED_INITIALIZER;里
if (i==0) {
                item.selected = YES;
                self.lastItem = item;
            }
            [self addSubview:item];     
- 在响应事件- (void)clickItem:(UIButton *)button{}里
self.lastItem.selected = NO;
button.selected = YES;
self.lastItem = button;     
六、设置动画
- 在响应事件- (void)clickItem:(UIButton *)button{}里
//设置动画
    [UIView animateWithDuration:0.2 animations:^{
        button.transform = CGAffineTransformMakeScale(1.2, 1.2);//先扩大到1.2
    }completion:^(BOOL finished) {
        [UIView animateWithDuration:0.2 animations:^{
            button.transform = CGAffineTransformIdentity;//恢复
        }];
    }];     
此时效果图:
 
     
七、添加中间的特殊item
- 在JHTabBar里
/** 中间的特殊item */
@property (nonatomic, strong) UIButton * midButton;     
- 懒加载
-(UIButton *)midButton{
    if (!_midButton) {
        _midButton = [UIButton buttonWithType:UIButtonTypeCustom];
        [_midButton setImage:[UIImage imageNamed:@"tab_middle"] forState:UIControlStateNormal];
        _midButton.tag = JHItemTypeMiddle;
        [_midButton addTarget:self action:@selector(clickItem:) forControlEvents:UIControlEventTouchUpInside];
    }
    return _midButton;
}     
- 在- (instancetype)initWithFrame:(CGRect)frame NS_DESIGNATED_INITIALIZER;for循环之后
//添加到视图
[self addSubview:self.midButton];     
- 在-(void)layoutSubviews{}里
[self.midButton sizeToFit];
self.midButton.center = CGPointMake(self.bounds.size.width/2, self.bounds.size.height-40);     
- command+n创建特殊视图
- 在JHTabBarViewController的代理方法里做修改
#pragma mark ---- 实现JHTabBarDelegate方法
-(void)tabBar:(JHTabBar *)tabBar clickBtn:(JHItemType)index{
    //不是特殊视图时
    if (index != JHItemTypeMiddle) {
        self.selectedIndex = index - JHItemTypeLeft;
        return;
    }
    //是模态视图
    middleVC * midVc = [[middleVC alloc]init];
    [self presentViewController:midVc animated:YES completion:nil];
}     
此时效果图:
 
     
 
		