自定义TabbarController, tabbarItem ,tabbar 屏幕适配

麹耘豪
2023-12-01

自定义TabbarController, tabbarItem ,tabbar 屏幕适配

tabbarItem
.h文件

//
//  JHKTabBarItem.h
//  TestBaseView
//
//  Created by 金英杰 on 2020/11/14.
//
@protocol JHKTabBarItemDelegate;
#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN




@interface JHKTabBarItem : UIView
@property (nonatomic, copy) NSString *icon;
@property (nonatomic, copy) NSString *title;
@property (nonatomic, strong) UIColor *titleColor;

@property (nonatomic, assign) id <JHKTabBarItemDelegate> delegate;



@end

@protocol JHKTabBarItemDelegate <NSObject>

- (void)tabBarItem:(JHKTabBarItem *)item didSelectIndex:(NSInteger)index;


@end
NS_ASSUME_NONNULL_END

.m文件

//
//  JHKTabBarItem.m
//  TestBaseView
//
//  Created by 金英杰 on 2020/11/14.
//

#import "JHKTabBarItem.h"
#import "JHKTabBarItem.h"

static NSInteger defaultTag = 100000;
@interface JHKTabBarItem ()

@property (nonatomic, strong)UIImageView *iconImageView;
@property (nonatomic, strong)UILabel *titleLabel;
@end

@implementation JHKTabBarItem
- (instancetype)init {
    self = [super init];
    if (self) {
        self.userInteractionEnabled = YES;
        UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(itemClicked:)];
        [self addGestureRecognizer:tap];
    }
    return self;
}
// 重写setTag方法
- (void)setTag:(NSInteger)tag {
    [super setTag:tag + defaultTag];
}

- (UIImageView *)iconImageView {
    if (_iconImageView == nil) {
        _iconImageView = [[UIImageView alloc]init];
        _iconImageView.contentMode = UIViewContentModeScaleAspectFit;
        [self addSubview:_iconImageView];
    }
    return _iconImageView;
}

- (UILabel *)titleLabel {
    if (_titleLabel == nil) {
        _titleLabel = [[UILabel alloc]init];
        _titleLabel.textAlignment = NSTextAlignmentCenter;
        _titleLabel.font = [UIFont systemFontOfSize:10];
        _titleLabel.numberOfLines = 0;
        _titleLabel.textColor = [UIColor grayColor];
        [self addSubview:_titleLabel];
    }
    return _titleLabel;
}

- (void)setIcon:(NSString *)icon {
    _icon = icon;
    self.iconImageView.image = [UIImage imageNamed:icon];
}

- (void)setTitle:(NSString *)title {
    _title = title;
    self.titleLabel.text = title;
}

- (void)setTitleColor:(UIColor *)titleColor {
    _titleColor = titleColor;
    self.titleLabel.textColor = titleColor;
}
- (void)layoutSubviews {
    [super layoutSubviews];
    CGFloat space = 6.0;
    if (self.icon.length > 0 && self.title.length > 0) {
        CGFloat iconHeight = (CGRectGetHeight(self.frame)- jTabBarBottomHeight - space * 3)*2/3.0 ;
        self.iconImageView.frame = CGRectMake(space, space, CGRectGetWidth(self.frame) - 2 * space, iconHeight);
        self.titleLabel.frame = CGRectMake(space, CGRectGetMaxY(self.iconImageView.frame) + space, CGRectGetWidth(self.frame) - 2*space,iconHeight/2.0);
    } else if (self.icon.length > 0) {
        self.iconImageView.frame = CGRectMake(2, 2, CGRectGetWidth(self.frame) - 4, CGRectGetHeight(self.frame) - 4);
    } else if (self.title.length > 0) {
        self.titleLabel.frame = CGRectMake(2, CGRectGetHeight(self.frame) - 22, CGRectGetWidth(self.frame) - 4, 20);
    }
}
- (void)itemClicked:(UITapGestureRecognizer *)tap {
    if (self.delegate && [self.delegate respondsToSelector:@selector(tabBarItem:didSelectIndex:)]) {
        [self.delegate tabBarItem:self didSelectIndex:self.tag - defaultTag];
    }
}

/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
    // Drawing code
}
*/

@end

tabbar
.h文件

//
//  JHKTabBar.h
//  TestBaseView
//
//  Created by 金英杰 on 2020/11/14.
//

#import <UIKit/UIKit.h>
@class JHKTabBarItem;
@protocol JHKTabBarDelegate;

NS_ASSUME_NONNULL_BEGIN

@interface JHKTabBar : UIView

@property (nonatomic, strong)NSArray<JHKTabBarItem *> *items;
@property (nonatomic, assign)id <JHKTabBarDelegate> delegate;

@end
@protocol JHKTabBarDelegate <NSObject>

- (void)tabBar:(JHKTabBar *)tab didSelectItem:(JHKTabBarItem *)item atIndex:(NSInteger)index ;
@end
NS_ASSUME_NONNULL_END

.m文件

//
//  JHKTabBar.m
//  TestBaseView
//
//  Created by 金英杰 on 2020/11/14.
//

#import "JHKTabBar.h"
#import "JHKTabBarItem.h"

@interface JHKTabBar ()<JHKTabBarItemDelegate>

@property (nonatomic, strong) UIVisualEffectView *effectView;
@property (nonatomic, strong) UIView *topLine;
@end
@implementation JHKTabBar

- (instancetype)init {
    self = [super init];
    if (self) {
        self.backgroundColor = [UIColor whiteColor];
    }
    return self;
}
- (UIView *)topLine {
    if (_topLine == nil) {
        _topLine = [[UIView alloc]init];
        _topLine.backgroundColor = jColorWithHex(0xC2C2C2);
        [self addSubview:_topLine];
    }
    return _topLine;
}

- (UIVisualEffectView *)effectView {
    if (_effectView == nil) {
        UIBlurEffect *effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
        _effectView = [[UIVisualEffectView alloc] initWithEffect:effect];
        _effectView.alpha = 1.0;
        [self addSubview:_effectView];
    }
    return _effectView;
}

- (void)layoutSubviews {
    [super layoutSubviews];
    self.effectView.frame = self.bounds;
    [self setupItems];
    self.topLine.frame = CGRectMake(0, 0, CGRectGetWidth(self.frame), 0.3);
}

- (void)setupItems {
    CGFloat width = CGRectGetWidth(self.frame)/self.items.count;
    CGFloat height = CGRectGetHeight(self.frame);
    for (int i = 0; i < self.items.count; i++) {
        JHKTabBarItem *item = [self.items objectAtIndex:i];
        item.frame = CGRectMake(i*width, 0, width, height);
        [self addSubview:item];
        item.delegate = self;
    }
}

- (void)tabBarItem:(JHKTabBarItem *)item didSelectIndex:(NSInteger)index {
    if (self.delegate && [self.delegate respondsToSelector:@selector(tabBar:didSelectItem:atIndex:)]) {
        [self.delegate tabBar:self didSelectItem:item atIndex:index];
    }
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
    // Drawing code
}
*/

@end

config文件
.h

//
//  JHKTabBarConfig.h
//  TestBaseView
//
//  Created by 金英杰 on 2020/11/14.
// 这个类的主要作用是: 提供数据源, 绘制底部tabBar, 及关联viewController;
#pragma mark - JHKTabBarConfig

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN

@interface JHKTabBarConfig : NSObject

/**
控制器数组, 必须设置
*/
@property (nonatomic, strong) NSArray *viewControllers;

/**
item标题数组, 选择设置
*/
@property (nonatomic, strong) NSArray *titles;

/**
是否是导航, 默认 YES
*/
@property (nonatomic, assign) BOOL isNavigation;

/**
选中状态下的图片数组
*/
@property (nonatomic, strong) NSArray *selectedImages;

/**
正常状态下的图片数组
*/
@property (nonatomic, strong) NSArray *normalImages;

/**
选中状态下的标题颜色 默认: red
*/
@property (nonatomic,strong) UIColor *selectedColor;
/**
正常状态下的标题颜色 默认: gray
*/
@property (nonatomic, strong) UIColor *normalColor;
@end

NS_ASSUME_NONNULL_END

.m

//
//  JHKTabBarConfig.m
//  TestBaseView
//
//  Created by 金英杰 on 2020/11/14.
//

#import "JHKTabBarConfig.h"

@implementation JHKTabBarConfig
- (instancetype)init {
    self = [super init];
        if (self) {
        _isNavigation = YES;
        _normalColor = [UIColor grayColor];
        _selectedColor = jColorWithHex(0xF85959);
    }
return self;
}
@end

controller
.h

//
//  JHKTabBarController.h
//  TestBaseView
//
//  Created by 金英杰 on 2020/11/14.
//

#import <UIKit/UIKit.h>
@class JHKTabBarConfig;
typedef JHKTabBarConfig*_Nonnull(^tabBarBlock)(JHKTabBarConfig * _Nullable config);

NS_ASSUME_NONNULL_BEGIN

@interface JHKTabBarController : UITabBarController
/**
是否可用自动旋转屏幕
*/
@property (nonatomic, assign) BOOL isAutoRotation;

/**
创建tabBarController

@param block 配置创建tabBarController所需的参数
@return 返回tabBarController实例对象
*/
+ (instancetype)createTabBarController:(tabBarBlock)block;

/**
获取当前的tabBarController实例, 实例创建后可通过此方法获取当前实例

@return 返回tabBarController实例对象
*/
+ (instancetype)defaultTabBarController;

/**
隐藏底部tabBar的方法

@param isAnimation 是否需要动画
*/
- (void)hiddenTabBarWithAnimation:(BOOL)isAnimation;

/**
显示底部tabBar的方法

@param isAnimation 是否需要动画
*/
- (void)showTabBarWithAnimation:(BOOL)isAnimation;

@end

NS_ASSUME_NONNULL_END

.m

//
//  JHKTabBarController.m
//  TestBaseView
//
//  Created by 金英杰 on 2020/11/14.
//

#import "JHKTabBarController.h"
#import "JHKTabBar.h"
#import "JHKTabBarConfig.h"
#import "JHKTabBarItem.h"
@interface JHKTabBarController ()<JHKTabBarDelegate>

@property (nonatomic, strong) JHKTabBar *customTabBar;
@property (nonatomic, strong) JHKTabBarConfig *config;
@end

@implementation JHKTabBarController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.navigationController.navigationBar.hidden = YES;
    self.view.backgroundColor = [UIColor whiteColor];
    self.selectedIndex = 0;
    // Do any additional setup after loading the view.
}
- (JHKTabBar *)customTabBar {

if (_customTabBar == nil) {
    _customTabBar = [[JHKTabBar alloc]init];
    _customTabBar.delegate = self;
}

return _customTabBar;
}

+ (instancetype)createTabBarController:(tabBarBlock)block {
    static dispatch_once_t onceToken;
    static JHKTabBarController *tabBar;
    dispatch_once(&onceToken, ^{
        tabBar = [[JHKTabBarController alloc]initWithBlock:block];
    });
    return tabBar;
}

+ (instancetype)defaultTabBarController {
    return [JHKTabBarController createTabBarController:nil];
}

- (void)hiddenTabBarWithAnimation:(BOOL)isAnimation {

    if (isAnimation) {

        [UIView animateWithDuration:0.2 animations:^{

            self.customTabBar.alpha = 0;
        }];
    } else {

        self.customTabBar.alpha = 0;
    }
}

- (void)showTabBarWithAnimation:(BOOL)isAnimation {

    if (isAnimation) {

        [UIView animateWithDuration:0.2 animations:^{

            self.customTabBar.alpha = 1.0;
        }];
    } else {

        self.customTabBar.alpha = 1.0;
    }
}

- (instancetype)initWithBlock:(tabBarBlock)block {
    self = [super init];
    if (self) {
        JHKTabBarConfig *config = [[JHKTabBarConfig alloc]init];
        
        NSAssert(block, @"Param in zhe function, can not be nil");
        if (block) {

            _config = block(config);
        }
        NSAssert(_config.viewControllers, @"Param 'viewControllers' in the 'config', can not be nil");
        [self setupViewControllers];
        [self setupTabBar];
        _isAutoRotation = YES;
}

    return self;
}

- (void)setupViewControllers {

    if (_config.isNavigation) {

        NSMutableArray *vcs = [NSMutableArray arrayWithCapacity:_config.viewControllers.count];
        for (UIViewController *vc in _config.viewControllers) {
            if (![vc isKindOfClass:[UINavigationController class]]) {
               // UINavigationController *nav = [[UINavigationController alloc]initWithRootViewController:vc];
                [vcs addObject:vc];
            } else {
                [vcs addObject:vc];
            }
        }

        self.viewControllers = [vcs copy];
    } else {

        self.viewControllers = [_config.viewControllers copy];
    }
}

- (void)setupTabBar {

    NSMutableArray *items = [NSMutableArray array];
    for (int i = 0; i < _config.viewControllers.count; i++) {
    JHKTabBarItem *item = [[JHKTabBarItem alloc]init];

        if (i == 0) {
            item.icon = _config.selectedImages[i];
            if (_config.titles.count > 0) {
            item.titleColor = _config.selectedColor;
            }
        } else {
            item.icon = _config.normalImages[i];
            if (_config.titles.count > 0) {
            item.titleColor = _config.normalColor;
            }
        }
        if (i < _config.titles.count) {
            item.title = _config.titles[i];
        }

        [items addObject:item];
        item.tag = i;
    }

    // 隐藏掉系统的tabBar
    self.tabBar.hidden = YES;
    self.customTabBar.items = [items copy];
    self.customTabBar.frame = CGRectMake(0, CGRectGetHeight(self.view.frame) - jTabbarHeight, CGRectGetWidth(self.view.frame), jTabbarHeight);
    [self.view addSubview:self.customTabBar];
}

#pragma mark - JHKTabBarDelegate
- (void)tabBar:(JHKTabBar *)tab didSelectItem:(JHKTabBarItem *)item atIndex:(NSInteger)index {
    NSMutableArray *items = [NSMutableArray arrayWithCapacity:0];
    for (UIView *view in tab.subviews) {
        if ([view isKindOfClass:[JHKTabBarItem class]]) {
            [items addObject:view];
        }
    }
    for (int i = 0; i < items.count; i++) {
        UIView *view = items[i];
        if ([view isKindOfClass:[JHKTabBarItem class]]) {
            JHKTabBarItem *item = (JHKTabBarItem *)view;
            item.icon = self.config.normalImages[i];
            if (self.config.titles.count > 0) {
                item.titleColor = _config.normalColor;
            }
        }
    }
    item.icon = self.config.selectedImages[index];
    if (self.config.titles.count > 0) {
        item.titleColor = self.config.selectedColor;
    }
    self.selectedIndex = index;
}

// 屏幕旋转时调整tabbar
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
    [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
    self.customTabBar.frame = CGRectMake(0, size.height - jTabbarHeight, size.width, jTabbarHeight);
}

- (BOOL)shouldAutorotate {
    return self.isAutoRotation;
}

- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
    if (self.isAutoRotation) {
        return UIInterfaceOrientationMaskAllButUpsideDown;
    } else {
        return UIInterfaceOrientationMaskPortrait;
    }
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/

@end

appdelegate中使用

   JHKTabBarConfig *tabBarConfig = [[JHKTabBarConfig alloc]init];

    tabBarConfig.viewControllers = @[vc,vc1,vc2,vc3];
    tabBarConfig.selectedImages = @[@"Image0",@"Image2",@"Image4",@"Image6"];
    tabBarConfig.normalImages = @[@"Image1",@"Image3",@"Image5",@"Image7"];
    tabBarConfig.titles = @[@"头条",@"西瓜视频",@"消息",@"放映厅"];

    JHKTabBarController *tabBarController = [JHKTabBarController createTabBarController:^JHKTabBarConfig *(JHKTabBarConfig *config) {
        return tabBarConfig;
    }];
    UINavigationController *controller = [[UINavigationController alloc]initWithRootViewController:tabBarController];
    tabBarController.navigationController.navigationBar.hidden = YES;

    self.window.rootViewController = controller;
    [self.window makeKeyAndVisible];

这里window的rootcontroller 要设置成nav下的tabbar。是因为 这个是自定义的tab 在push的时候没法使用 hidenavwhenpush 那个方法来隐藏tabbar

 类似资料: