iOS 簡單的自定義凸起(不規則)tabbar

主要實現思路:
1.重寫UITabBar:在init裏面創建一個button來實現不規則的圖標(添加新按鈕)放在最中間 -(void)layoutSubviews調整系統原本的圖標的座標(爲中間這個控件留出位置)
2.重寫-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{ 避免按鈕超區不可點擊

看具體的代碼:
自定義SamTabBar視圖

//
//  SamTabBar.h
//  MoJing
//
//  Created by linpeng on 2017/3/15.
//  Copyright © 2017年 linpeng. All rights reserved.
//

#import <UIKit/UIKit.h>
//tab頁面個數
typedef NS_ENUM(NSInteger, SamItemUIType) {
    SamItemUIType_Three = 3,//底部3個選項
    SamItemUIType_Five = 5,//底部5個選項
};


@class SamTabBar;

@protocol SamTabBarDelegate <NSObject>

-(void)tabBar:(SamTabBar *)tabBar clickCenterButton:(UIButton *)sender;

@end

@interface SamTabBar : UITabBar

@property (nonatomic, weak) id<SamTabBarDelegate> tabDelegate;
@property (nonatomic, strong) NSString *centerBtnTitle;
@property (nonatomic, strong) NSString *centerBtnIcon;

+(instancetype)instanceCustomTabBarWithType:(SamItemUIType)type;

@end

m文件

//
//  SamTabBar.m
//  MoJing
//
//  Created by linpeng on 2017/3/15.
//  Copyright © 2017年 linpeng. All rights reserved.
//

#import "SamTabBar.h"

@interface SamTabBar()
@property(nonatomic, strong) UIButton *centerButton;
@property(nonatomic, strong) UILabel *centerTitle;
@property (nonatomic,assign) SamItemUIType type;

@end

@implementation SamTabBar

+(instancetype)instanceCustomTabBarWithType:(SamItemUIType)type{
    SamTabBar *tabBar = [[SamTabBar alloc] init];
    tabBar.type = type;
    return tabBar;
}

-(instancetype)initWithFrame:(CGRect)frame{
    self = [super initWithFrame:frame];
    if (self) {
        self.translucent = NO;
        UIButton *plusBtn = [UIButton buttonWithType:UIButtonTypeCustom];
        self.centerButton = plusBtn;
        [plusBtn addTarget:self action:@selector(plusBtnDidClick) forControlEvents:UIControlEventTouchUpInside];
        [self addSubview:plusBtn];

        UILabel *lblTitle = [[UILabel alloc] init];
        self.centerTitle = lblTitle;
        lblTitle.font = [UIFont systemFontOfSize:10];
        lblTitle.textColor = [UIColor blackColor];
        lblTitle.textAlignment = NSTextAlignmentCenter;
        [self addSubview:lblTitle];

    }
    return self;
}

-(void)plusBtnDidClick{
    if (self.tabDelegate && [self.tabDelegate respondsToSelector:@selector(tabBar:clickCenterButton:)]) {
        [self.tabDelegate tabBar:self clickCenterButton:self.centerButton];
    }
}

// 調整子視圖的佈局
-(void)layoutSubviews{
    [super layoutSubviews];
    CGFloat width = self.frame.size.width/self.type;
    Class class = NSClassFromString(@"UITabBarButton");
    for (UIView *view in self.subviews) {
        if ([view isEqual:self.centerTitle]) {//self.centerButton
            view.frame = CGRectMake(0, 0, width, 15);
            view.center = CGPointMake(self.frame.size.width/2, self.frame.size.height - view.frame.size.height + 8);
        }else if ([view isEqual:self.centerButton]) {//self.centerButton
            view.frame = CGRectMake(0, 0, width, self.frame.size.height);
            [view sizeToFit];
            view.center = CGPointMake(self.frame.size.width/2, 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 >= (self.type - 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.centerButton];

        //判斷如果這個新的點是在發佈按鈕身上,那麼處理點擊事件最合適的view就是發佈按鈕
        if ( [self.centerButton pointInside:newP withEvent:event]) {
            return self.centerButton;
        }else{//如果點不在發佈按鈕身上,直接讓系統處理就可以了
            return [super hitTest:point withEvent:event];
        }
    }
    else {//tabbar隱藏了,那麼說明已經push到其他的頁面了,這個時候還是讓系統去判斷最合適的view處理就好了
        return [super hitTest:point withEvent:event];
    }
}

-(void)setCenterBtnIcon:(NSString *)centerBtnIcon{
    _centerBtnIcon = centerBtnIcon;
    [self.centerButton setBackgroundImage:[UIImage imageNamed:self.centerBtnIcon] forState:UIControlStateNormal];
    [self.centerButton setBackgroundImage:[UIImage imageNamed:self.centerBtnIcon] forState:UIControlStateHighlighted];
}

-(void)setCenterBtnTitle:(NSString *)centerBtnTitle{
    _centerBtnTitle = centerBtnTitle;
    self.centerTitle.text = centerBtnTitle;
}

@end

用法:
以上自定義的tabbar控件就弄好了 現在就可以在VC中使用了
創建一個WBTabBarController 繼承UITabBarController 在appdelegate中

self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    self.window.rootViewController = [[WBTabBarController alloc] init];

kvo的形式添加自定義的tabbar

 //kvo形式添加自定義的 UITabBar
    SamTabBar *tab = [SamTabBar instanceCustomTabBarWithType:SamItemUIType_Five];
    [self setValue:tab forKey:@"tabBar"];

具體的代碼:

@interface WBTabBarController ()<SamTabBarDelegate>
@end

@implementation WBTabBarController

- (void)awakeFromNib {
    [super awakeFromNib];
}

- (void)viewDidLoad {
    [super viewDidLoad];
    [self setupUI];
}

-(void)setupUI{
    [self setupVC];
    [[UITabBar appearance] setShadowImage:[UIImage new]];
    //kvo形式添加自定義的 UITabBar
    SamTabBar *tab = [SamTabBar instanceCustomTabBarWithType:SamItemUIType_Five];
    tab.centerBtnTitle = @"發佈";
    tab.centerBtnIcon = @"攝影機圖標_點擊後";
    tab.tabDelegate = self;
    [self setValue:tab forKey:@"tabBar"];
}

- (void)setupVC{
    [self addChildVc:[[LoginViewController alloc] init] title:@"首頁" image:@"TabMessage" selectedImage:@"TabMessage_HL"];
    [self addChildVc:[[LoginViewController alloc] init] title:@"發現" image:@"TabMessage" selectedImage:@"TabMessage_HL"];
    [self addChildVc:[[LoginViewController alloc] init] title:@"消息" image:@"TabMessage" selectedImage:@"TabMessage_HL"];
    [self addChildVc:[[LoginViewController alloc] init] title:@"個人中心" image:@"TabMessage" selectedImage:@"TabMessage_HL"];
}

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

-(void)tabBar:(SamTabBar *)tabBar clickCenterButton:(UIButton *)sender{
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提示" message:@"點擊了中間按鈕" preferredStyle:UIAlertControllerStyleAlert];
    UIAlertAction *action = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {

    }];
    [alert addAction:action];
    [self presentViewController:alert animated:YES completion:nil];
}

- (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

效果如圖:
圖片

gif效果如圖:
gif效果

修改tabbar上那條很醜的分割線

-(void)setupUI{
    [self setupVC];
    //kvo形式添加自定義的 UITabBar
    SamTabBar *tab = [SamTabBar instanceCustomTabBarWithType:SamItemUIType_Five];
    tab.centerBtnTitle = nil;
    tab.centerBtnIcon = @"menu_diary_pr";
    tab.tabDelegate = self;
    [self setValue:tab forKey:@"tabBar"];

    //去除頂部很醜的border
    [[UITabBar appearance] setShadowImage:[UIImage new]];
    [[UITabBar appearance] setBackgroundImage:[[UIImage alloc]init]];

    //自定義分割線顏色
    UIView *bgView = [[UIView alloc] initWithFrame:CGRectMake(self.tabBar.bounds.origin.x-0.5, self.tabBar.bounds.origin.y, self.tabBar.bounds.size.width+1, self.tabBar.bounds.size.height+2)];
    bgView.layer.borderColor = COLOR_SEPERATOR.CGColor;
    bgView.layer.borderWidth = 0.5;
    [tab insertSubview:bgView atIndex:0];
    tab.opaque = YES;
}

效果:
這裏寫圖片描述

發佈了135 篇原創文章 · 獲贊 31 · 訪問量 32萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章