UITabBarController的使用自定义UITabBar样式

UITabBarController的使用过程中,可能会出现需要自定义UITabBar样式的时候,下面介绍两种实现方法。

方法1
存在N个视图控制器,且需要使用自定义的UITabBar样式来进行交互操作哪个视图控制器的显示。具体做法是在UITabBarController中的view中添加自定义样式的子视图,设置子视图响应方法跳转对应的视图控制器,然后再通过UITabBarController的代理方法重置自定义样式的子视图状态。

代码示例,继承UITabBarController的方式实现

#import "BaseTabBarController.h"
#import "MainVC.h"
#import "MineVC.h"
#import "AddVC.h"

@interface BaseTabBarController () 

@property (nonatomic, strong) UIButton *addButton;

@end

@implementation BaseTabBarController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    [self initlizeAddButton];
}

#pragma mark - 实现

- (void)initlizeAddButton
{
    self.delegate = self;
    [self addChildVc:[[MainVC alloc] init] title:@"首页" image:@"homeNormal" selectedImage:@"homeSelected"];
    [self addChildVc:[[AddVC alloc] init] title:nil image:nil selectedImage:nil];
    [self addChildVc:[[MineVC alloc] init] title:@"我的" image:@"mineNormal" selectedImage:@"mineSelected"];

    self.tabBar.backgroundColor = [UIColor yellowColor];
    
    self.addButton = [[UIButton alloc] initWithFrame:CGRectMake((self.tabBar.frame.size.width - 70.0) / 2, (self.view.frame.size.height - 70.0) - 44.0, 70.0, 70.0)];
    self.addButton.backgroundColor = [UIColor yellowColor];
    self.addButton.layer.cornerRadius = 35;
    self.addButton.layer.masksToBounds = YES;
    [self.addButton setImage:[UIImage imageNamed:@"addNormal"] forState:UIControlStateNormal];
    [self.addButton setImage:[UIImage imageNamed:@"addSelected"] forState:UIControlStateSelected];
    [self.addButton addTarget:self action:@selector(addClick:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:self.addButton];
    [self.view bringSubviewToFront:self.addButton];
}

- (void)addClick:(UIButton *)button
{
    button.selected = YES;
    button.userInteractionEnabled = NO;
    self.selectedIndex = 1;
}

- (void)addChildVc:(UIViewController *)childVc title:(NSString *)title image:(NSString *)image selectedImage:(NSString *)selectedImage
{
    // 设置子控制器的文字(可以设置tabBar和navigationBar的文字)
    if (title) {
        childVc.title = title;
    }
    
    // 设置子控制器的tabBarItem图片
    if (image) {
        childVc.tabBarItem.image = [UIImage imageNamed:image];
    }
    
    // 禁用图片渲染
    if (selectedImage) {
        childVc.tabBarItem.selectedImage = [[UIImage imageNamed:selectedImage] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
    }
    
    // 设置文字的样式
    [childVc.tabBarItem setTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColor blackColor]} forState:UIControlStateNormal];
    [childVc.tabBarItem setTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColor redColor]} forState:UIControlStateSelected];
    // 为子控制器包装导航控制器
    UINavigationController *navigationVc = [[UINavigationController alloc] initWithRootViewController:childVc];
    // 添加子控制器
    [self addChildViewController:navigationVc];
}

#pragma mark - delegate

- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController
{
    // 方法2 时
    if (self.addButton) {
        self.addButton.selected = NO;
        self.addButton.userInteractionEnabled = YES;
    }
    return YES;
}

@end

效果图
UITabBarController的使用自定义UITabBar样式_第1张图片

方法2
存在N个视图控制器,且需要使用自定义的UITabBar样式来进行交互操作其他,N为偶数;如有两个视图控制器,然后自定义的样式控制其他视图。具体做法继承UITabBar,并在UITabBarController中设置。

代码示例,继承UITabBarController的方式实现

#import 

@protocol AddItemTabBarDelegate 

- (void)tabBarItemClick:(UIButton *)button;

@end

@interface AddItemTabBar : UITabBar

@property (nonatomic, weak) iddelegate;

@property (nonatomic, strong) UIButton *button;
@property (nonatomic, strong) UILabel *label;

/// 根据实际的视图数组数设置(如:实际的UITabBarController的viewControllers数量为2,则为2)
@property (nonatomic, assign) NSInteger number;

@end

#import "AddItemTabBar.h"

@interface AddItemTabBar ()

@end

@implementation AddItemTabBar

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        self.translucent = NO;
        //
        self.button = [UIButton buttonWithType:UIButtonTypeCustom];
        self.button.backgroundColor = [UIColor greenColor];
        self.button.layer.masksToBounds = YES;
        [self.button setImage:[UIImage imageNamed:@"addNormal"] forState:UIControlStateNormal];
        [self.button setImage:[UIImage imageNamed:@"addSelected"] forState:UIControlStateSelected];
        [self.button addTarget:self action:@selector(plusBtnDidClick) forControlEvents:UIControlEventTouchUpInside];
        [self addSubview:self.button];
        //
        self.label = [[UILabel alloc] init];
        self.label.font = [UIFont systemFontOfSize:10];
        self.label.textColor = [UIColor blackColor];
        self.label.textAlignment = NSTextAlignmentCenter;
        [self addSubview:self.label];
    }
    return self;
}

- (void)plusBtnDidClick
{
    if (self.delegate && [self.delegate respondsToSelector:@selector(tabBarItemClick:)]) {
        [self.delegate tabBarItemClick:self.button];
    }
}

// 调整子视图的布局
- (void)layoutSubviews
{
    [super layoutSubviews];
    CGFloat width = self.frame.size.width / (self.number + 1);
    Class class = NSClassFromString(@"UITabBarButton");
    for (UIView *view in self.subviews) {
        if ([view isEqual:self.label]) {
            // self.label
            view.frame = CGRectMake(0, 0, width, 15);
            view.center = CGPointMake(self.frame.size.width / self.number, self.frame.size.height - view.frame.size.height + 8);
        } else if ([view isEqual:self.button]) {
            // self.button
            CGSize size = CGSizeMake(width, self.frame.size.height);
            size = CGSizeMake(80.0, 80.0);
            view.layer.cornerRadius = size.width / 2;
            view.frame = CGRectMake(0, 0, size.width, size.height);
//            [view sizeToFit];
            view.center = CGPointMake(self.frame.size.width / self.number, 10);
        } else if ([view isKindOfClass:class]) {
            // system button
            CGRect frame = view.frame;
            int indexFromOrign = view.frame.origin.x/width;
            // 防止UIView *view in self.subviews 获取到的不是有序的
            if (indexFromOrign >= (3 - 1) / 2) {
                indexFromOrign++;
            }
            CGFloat x = indexFromOrign * width;
            //如果是系统的UITabBarButton,那么就调整子控件位置,空出中间位置
            view.frame = CGRectMake(x, view.frame.origin.y, width, frame.size.height);
            
            // 调整badge postion
            for (UIView *badgeView in view.subviews){
                NSString *className = NSStringFromClass([badgeView class]);
                // Looking for _UIBadgeView
                if ([className rangeOfString:@"BadgeView"].location != NSNotFound) {
                    badgeView.layer.transform = CATransform3DIdentity;
                    badgeView.layer.transform = CATransform3DMakeTranslation(-17.0, 1.0, 1.0);
                    break;
                }
            }
        }
    }
}


- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    // 这一个判断是关键,不判断的话push到其他页面,点击发布按钮的位置也是会有反应的,这样就不好了
    // self.isHidden == NO 说明当前页面是有tabbar的,那么肯定是在导航控制器的根控制器页面
    // 在导航控制器根控制器页面,那么我们就需要判断手指点击的位置是否在发布按钮身上
    // 是的话让发布按钮自己处理点击事件,不是的话让系统去处理点击事件就可以了
    if (self.isHidden == NO) {
        // 将当前tabbar的触摸点转换坐标系,转换到发布按钮的身上,生成一个新的点
        CGPoint newP = [self convertPoint:point toView:self.button];
        
        // 判断如果这个新的点是在发布按钮身上,那么处理点击事件最合适的view就是发布按钮
        if ( [self.button pointInside:newP withEvent:event]) {
            return self.button;
        } else {
            //如果点不在发布按钮身上,直接让系统处理就可以了
            return [super hitTest:point withEvent:event];
        }
    } else {
        //tabbar隐藏了,那么说明已经push到其他的页面了,这个时候还是让系统去判断最合适的view处理就好了
        return [super hitTest:point withEvent:event];
    }
}

@end
@interface BaseTabBarController : UITabBarController

@property (nonatomic, copy) void (^showClick)(UIButton *button);

@end

#import "BaseTabBarController.h"
#import "MainVC.h"
#import "MineVC.h"
#import "AddVC.h"

#import "AddItemTabBar.h"

@interface BaseTabBarController () 

@property (nonatomic, strong) UIButton *addButton;

@end

@implementation BaseTabBarController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    //  自定义样式
    [self initlizeAddItemController];
}

#pragma mark - 自定义tabbarItem

- (void)initlizeAddItemController
{
    [self setupVC];
    
    AddItemTabBar *tab = [[AddItemTabBar alloc] initWithFrame:CGRectZero];
    tab.number = 2;
    tab.delegate = self;
    [self setValue:tab forKey:@"tabBar"];
}

- (void)setupVC
{
    self.delegate = self;
    
    [self addChildVc:[[MainVC alloc] init] title:@"首页" image:@"homeNormal" selectedImage:@"homeSelected"];
    [self addChildVc:[[MineVC alloc] init] title:@"我的" image:@"mineNormal" selectedImage:@"mineSelected"];
}

- (void)addChildVc:(UIViewController *)childVc title:(NSString *)title image:(NSString *)image selectedImage:(NSString *)selectedImage
{
    // 设置子控制器的文字(可以设置tabBar和navigationBar的文字)
    if (title) {
        childVc.title = title;
    }
    
    // 设置子控制器的tabBarItem图片
    if (image) {
        childVc.tabBarItem.image = [UIImage imageNamed:image];
    }
    
    // 禁用图片渲染
    if (selectedImage) {
        childVc.tabBarItem.selectedImage = [[UIImage imageNamed:selectedImage] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
    }
    
    // 设置文字的样式
    [childVc.tabBarItem setTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColor blackColor]} forState:UIControlStateNormal];
    [childVc.tabBarItem setTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColor redColor]} forState:UIControlStateSelected];
    // 为子控制器包装导航控制器
    UINavigationController *navigationVc = [[UINavigationController alloc] initWithRootViewController:childVc];
    // 添加子控制器
    [self addChildViewController:navigationVc];
}

- (void)tabBarItemClick:(UIButton *)button
{
    button.selected = !button.selected;
    if (self.addButton == nil) {
        self.addButton = button;
    }
    if (self.showClick) {
        self.showClick(button);
    }
}

#pragma mark - delegate

- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController
{
    if (self.addButton) {
        self.addButton.selected = NO;
    }

    UIApplication.sharedApplication.delegate.window.backgroundColor = [UIColor whiteColor];
    
    return YES;
}

@end
 BaseTabBarController *rootVC = [[BaseTabBarController alloc] init];
    self.window.rootViewController = rootVC;
    self.window.backgroundColor = [UIColor whiteColor];
    [self.window makeKeyAndVisible];
    
    rootVC.showClick = ^(UIButton * _Nonnull button) {
        self.window.backgroundColor = [UIColor orangeColor];
    };

效果图
UITabBarController的使用自定义UITabBar样式_第2张图片

你可能感兴趣的:(iOS,视图控制器)