【終極】中間加號凸出的tabbar(OC)

1、需要兩個類:
(1)TBTabBar

#import <UIKit/UIKit.h>

@interface TBTabBar : UITabBar

//@property(nonatomic,strong)UIButton *publishBtn;

@property (nonatomic,copy) void(^didClickPublishBtn)();

@end

#import "TBTabBar.h"
//button拓展類
#import "UIButton+SSEdgeInsets.h"

@interface TBTabBar ()

/** plus按鈕 */
@property (nonatomic, weak) UIButton *plusBtn ;

@end

@implementation TBTabBar

- (void)layoutSubviews {
    [super layoutSubviews];
    
    CGFloat w = self.width/5.0;
    
    UIButton *publishBtn = [[UIButton alloc] init];
    [publishBtn setImage:[UIImage imageNamed:@"發(fā)布3.3"] forState:UIControlStateNormal];
    [publishBtn setTitle:@"  " forState:UIControlStateNormal];
    publishBtn.titleLabel.font = [UIFont systemFontOfSize:10];
    [publishBtn addTarget:self action:@selector(didClickPublishBtn:) forControlEvents:UIControlEventTouchUpInside];
    publishBtn.adjustsImageWhenHighlighted = NO;
    publishBtn.size = CGSizeMake(w, 70);
    publishBtn.centerX = self.width / 2;
    publishBtn.centerY = 12;
    [publishBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
    [self addSubview:publishBtn];
    self.plusBtn = publishBtn;
    //button按鈕
    [publishBtn setImagePositionWithType:SSImagePositionTypeTop spacing:5];
    
    
    // 其他位置按鈕
    NSUInteger count = self.subviews.count;
    for (NSUInteger i = 0 , j = 0; i < count; i++) {
        UIView *view = self.subviews[i];
        Class class = NSClassFromString(@"UITabBarButton");
        if ([view isKindOfClass:class]) {
            view.width = self.width / 5.0;
            view.x = self.width * j / 5.0;
            
            j++;
            if (j == 2) {
                j++;
            }
        }
    }
    
}

// 點擊發(fā)布
- (void) didClickPublishBtn:(UIButton*)sender {
    //    NSLog(@"點擊了發(fā)布");
    if (self.didClickPublishBtn) {
        self.didClickPublishBtn();
    }
}

//重寫hitTest方法,去監(jiān)聽發(fā)布按鈕的點擊瞒窒,目的是為了讓凸出的部分點擊也有反應
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    
    //這一個判斷是關鍵崇裁,不判斷的話push到其他頁面拔稳,點擊發(fā)布按鈕的位置也是會有反應的壳炎,這樣就不好了
    //self.isHidden == NO 說明當前頁面是有tabbar的匿辩,那么肯定是在導航控制器的根控制器頁面
    //在導航控制器根控制器頁面铲球,那么我們就需要判斷手指點擊的位置是否在發(fā)布按鈕身上
    //是的話讓發(fā)布按鈕自己處理點擊事件稼病,不是的話讓系統(tǒng)去處理點擊事件就可以了
    if (self.isHidden == NO) {
        
        //將當前tabbar的觸摸點轉換坐標系然走,轉換到發(fā)布按鈕的身上,生成一個新的點
        CGPoint newP = [self convertPoint:point toView:self.plusBtn];
        
        //判斷如果這個新的點是在發(fā)布按鈕身上晨仑,那么處理點擊事件最合適的view就是發(fā)布按鈕
        if ( [self.plusBtn pointInside:newP withEvent:event]) {
            return self.plusBtn;
        }else{//如果點不在發(fā)布按鈕身上洪己,直接讓系統(tǒng)處理就可以了
            
            return [super hitTest:point withEvent:event];
        }
    }
    
    else {//tabbar隱藏了答捕,那么說明已經(jīng)push到其他的頁面了拱镐,這個時候還是讓系統(tǒng)去判斷最合適的view處理就好了
        
        return [super hitTest:point withEvent:event];
    }
}

@end

(2)UIButton+SSEdgeInsets

#import <UIKit/UIKit.h>

typedef NS_ENUM(NSInteger, SSImagePositionType) {
    SSImagePositionTypeLeft,   //圖片在左持际,標題在右选酗,默認風格
    SSImagePositionTypeRight,  //圖片在右芒填,標題在左
    SSImagePositionTypeTop,    //圖片在上殿衰,標題在下
    SSImagePositionTypeBottom  //圖片在下,標題在上
};

typedef NS_ENUM(NSInteger, SSEdgeInsetsType) {
    SSEdgeInsetsTypeTitle,//標題
    SSEdgeInsetsTypeImage//圖片
};

typedef NS_ENUM(NSInteger, SSMarginType) {
    SSMarginTypeTop         ,
    SSMarginTypeBottom      ,
    SSMarginTypeLeft        ,
    SSMarginTypeRight       ,
    SSMarginTypeTopLeft     ,
    SSMarginTypeTopRight    ,
    SSMarginTypeBottomLeft  ,
    SSMarginTypeBottomRight
};

/**
 默認情況下娱颊,imageEdgeInsets和titleEdgeInsets都是0箱硕。先不考慮height,
 
 if (button.width小于imageView上image的width){圖像會被壓縮,文字不顯示}
 
 if (button.width < imageView.width + label.width){圖像正常顯示栓拜,文字顯示不全}
 
 if (button.width >= imageView.width + label.width){圖像和文字都居中顯示幕与,imageView在左啦鸣,label在右诫给,中間沒有空隙}
 */

@interface UIButton (SSEdgeInsets)

/**
 *  利用UIButton的titleEdgeInsets和imageEdgeInsets來實現(xiàn)圖片和標題的自由排布
 *  注意:1.該方法需在設置圖片和標題之后才調用;
         2.圖片和標題改變后需再次調用以重新計算titleEdgeInsets和imageEdgeInsets
 *
 *  @param type    圖片位置類型
 *  @param spacing 圖片和標題之間的間隙
 */
- (void)setImagePositionWithType:(SSImagePositionType)type spacing:(CGFloat)spacing;

/**
 *  按鈕只設置了title or image蝙搔,該方法可以改變它們的位置
 *
 *  @param edgeInsetsType <#edgeInsetsType description#>
 *  @param marginType     <#marginType description#>
 *  @param margin         <#margin description#>
 */
- (void)setEdgeInsetsWithType:(SSEdgeInsetsType)edgeInsetsType marginType:(SSMarginType)marginType margin:(CGFloat)margin;



/**
 *  圖片在上,標題在下
 *
 *  @param spacing image 和 title 之間的間隙
 */
- (void)setImageUpTitleDownWithSpacing:(CGFloat)spacing __deprecated_msg("Method deprecated. Use `setImagePositionWithType:spacing:`");

/**
 *  圖片在右证鸥,標題在左
 *
 *  @param spacing image 和 title 之間的間隙
 */
- (void)setImageRightTitleLeftWithSpacing:(CGFloat)spacing __deprecated_msg("Method deprecated. Use `setImagePositionWithType:spacing:`");

@end

#import "UIButton+SSEdgeInsets.h"

#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000
#define SS_SINGLELINE_TEXTSIZE(text, font) [text length] > 0 ? [text \
sizeWithAttributes:@{NSFontAttributeName:font}] : CGSizeZero;
#else
#define SS_SINGLELINE_TEXTSIZE(text, font) [text length] > 0 ? [text sizeWithFont:font] : CGSizeZero;
#endif

@implementation UIButton (SSEdgeInsets)

- (void)setImagePositionWithType:(SSImagePositionType)type spacing:(CGFloat)spacing {
    CGSize imageSize = [self imageForState:UIControlStateNormal].size;
    CGSize titleSize = SS_SINGLELINE_TEXTSIZE([self titleForState:UIControlStateNormal], self.titleLabel.font);

    switch (type) {
        case SSImagePositionTypeLeft: {
            self.titleEdgeInsets = UIEdgeInsetsMake(0, spacing, 0, 0);
            self.imageEdgeInsets = UIEdgeInsetsMake(0, 0, 0, spacing);
            break;
        }
        case SSImagePositionTypeRight: {
            self.titleEdgeInsets = UIEdgeInsetsMake(0, - imageSize.width, 0, imageSize.width + spacing);
            self.imageEdgeInsets = UIEdgeInsetsMake(0, titleSize.width + spacing, 0, - titleSize.width);
            break;
        }
        case SSImagePositionTypeTop: {
            // lower the text and push it left so it appears centered
            //  below the image
            self.titleEdgeInsets = UIEdgeInsetsMake(0, - imageSize.width, - (imageSize.height + spacing), 0);
            
            // raise the image and push it right so it appears centered
            //  above the text
            self.imageEdgeInsets = UIEdgeInsetsMake(- (titleSize.height + spacing), 0, 0, - titleSize.width);
            break;
        }
        case SSImagePositionTypeBottom: {
            self.titleEdgeInsets = UIEdgeInsetsMake(- (imageSize.height + spacing), - imageSize.width, 0, 0);
            self.imageEdgeInsets = UIEdgeInsetsMake(0, 0, - (titleSize.height + spacing), - titleSize.width);
            break;
        }
    }
}

- (void)setImageUpTitleDownWithSpacing:(CGFloat)spacing {
    [self setImagePositionWithType:SSImagePositionTypeTop spacing:spacing];
}

- (void)setImageRightTitleLeftWithSpacing:(CGFloat)spacing {
    [self setImagePositionWithType:SSImagePositionTypeRight spacing:spacing];
}

- (void)setEdgeInsetsWithType:(SSEdgeInsetsType)edgeInsetsType marginType:(SSMarginType)marginType margin:(CGFloat)margin {
    CGSize itemSize = CGSizeZero;
    if (edgeInsetsType == SSEdgeInsetsTypeTitle) {
        itemSize = SS_SINGLELINE_TEXTSIZE([self titleForState:UIControlStateNormal], self.titleLabel.font);
    } else {
        itemSize = [self imageForState:UIControlStateNormal].size;
    }
    
    CGFloat horizontalDelta = (CGRectGetWidth(self.frame) - itemSize.width) / 2.f - margin;
    CGFloat vertivalDelta = (CGRectGetHeight(self.frame) - itemSize.height) / 2.f - margin;
    
    NSInteger horizontalSignFlag = 1;
    NSInteger verticalSignFlag = 1;
    
    switch (marginType) {
        case SSMarginTypeTop: {
            horizontalSignFlag = 0;
            verticalSignFlag = - 1;
            break;
        }
        case SSMarginTypeBottom: {
            horizontalSignFlag = 0;
            verticalSignFlag = 1;
            break;
        }
        case SSMarginTypeLeft: {
            horizontalSignFlag = - 1;
            verticalSignFlag = 0;
            break;
        }
        case SSMarginTypeRight: {
            horizontalSignFlag = 1;
            verticalSignFlag = 0;
            break;
        }
        case SSMarginTypeTopLeft: {
            horizontalSignFlag = - 1;
            verticalSignFlag = - 1;
            break;
        }
        case SSMarginTypeTopRight: {
            horizontalSignFlag = 1;
            verticalSignFlag = - 1;
            break;
        }
        case SSMarginTypeBottomLeft: {
            horizontalSignFlag = - 1;
            verticalSignFlag = 1;
            break;
        }
        case SSMarginTypeBottomRight: {
            horizontalSignFlag = 1;
            verticalSignFlag = 1;
            break;
        }
    }
    
    UIEdgeInsets edgeInsets = UIEdgeInsetsMake(vertivalDelta * verticalSignFlag, horizontalDelta * horizontalSignFlag, - vertivalDelta * verticalSignFlag, - horizontalDelta * horizontalSignFlag);
    if (edgeInsetsType == SSEdgeInsetsTypeTitle) {
        self.titleEdgeInsets = edgeInsets;
    } else {
        self.imageEdgeInsets = edgeInsets;
    }
}

@end

2膜赃、控制器里:MainViewController

#import <UIKit/UIKit.h>

@interface MainViewController : UITabBarController

@end

#import "MainViewController.h"
//tabbar
#import "TBTabBar.h"
//導航欄
#import "MineNavigationController.h"
//主頁
#import "MainHomeViewControllerV3_3.h"
//逛街
#import "ShoppingViewController.h"
//美聊
#import "BeautyChatControllerV2_0.h"
//個人中心3.1.0
#import "MyCenterViewController3_1_0.h"
//發(fā)布話題
#import "SendTopicViewController.h"

@interface MainViewController ()
/** 之前被選中的UITabBarItem */
@property (nonatomic, strong) UITabBarItem *lastItem;

@end

@implementation MainViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 初始化所有控制器
    [self setUpChildVC];
    
    // 創(chuàng)建tabbar中間的tabbarItem
    [self setUpMidelTabbarItem];
    
}

#pragma mark -創(chuàng)建tabbar中間的tabbarItem

- (void)setUpMidelTabbarItem {
    
    TBTabBar *tabBar = [[TBTabBar alloc] init];
     // KVC:如果要修系統(tǒng)的某些屬性跳座,但被設為readOnly疲眷,就是用KVC狂丝,即setValue:forKey:。
    [self setValue:tabBar forKey:@"tabBar"];
    
    //去掉黑線,然后替換tabbar上面那一條線,下面兩個方法必須同時設置倍试,否則無效imageWithColor是根據(jù)顏色生成圖片的封裝
    [tabBar setBackgroundImage:[UIImage imageWithColor:[UIColor whiteColor] size:CGSizeMake(self.view.frame.size.width, .5)]];
    [tabBar setShadowImage:[UIImage imageWithColor:[UIColor colorWithHexString:@"#d1d3db"] size:CGSizeMake(self.view.frame.size.width, .5)]];
    
    
    //(3)設置其他屬性
    tabBar.barTintColor = [UIColor whiteColor];//設置tabbar背景顏色
    tabBar.translucent = NO;
   
    
    // 二次點擊觸發(fā)刷新將默認被選中的tabBarItem保存為屬性
    self.lastItem = tabBar.selectedItem;
    

    
    //中間發(fā)布按鈕點擊回調
    __weak typeof(self) weakSelf = self;
    [tabBar setDidClickPublishBtn:^{
        
        //凸出按鈕點擊事件
        [weakSelf plusBtnClick];
        
    }];
    
}

#pragma mark -初始化所有控制器

- (void)setUpChildVC {
    
    MainHomeViewControllerV3_3 *homeVC = [[MainHomeViewControllerV3_3 alloc] init];
    //設置角標數(shù)量
//    homeVC.tabBarItem.badgeValue = @"1111";
    [self setChildVC:homeVC title:@"" image:@"首頁" selectedImage:@"首頁s"];
    
    ShoppingViewController *fishpidVC = [[ShoppingViewController alloc] init];
    [self setChildVC:fishpidVC title:@"" image:@"逛街" selectedImage:@"逛街s"];
    
    BeautyChatControllerV2_0 *messageVC = [[BeautyChatControllerV2_0 alloc] init];
    [self setChildVC:messageVC title:@"" image:@"美聊"  selectedImage:@"美聊s"];
    
    MyCenterViewController3_1_0 *myVC = [[MyCenterViewController3_1_0 alloc] init];
    [self setChildVC:myVC title:@"" image:@"我的" selectedImage:@"我的s"];
    
  
    
}

//設置子控制器
- (void) setChildVC:(UIViewController *)childVC title:(NSString *) title image:(NSString *) image selectedImage:(NSString *) selectedImage {
    
    childVC.tabBarItem.title = title;
    //設置字體屬性
    NSMutableDictionary *dict = [NSMutableDictionary dictionary];
    dict[NSForegroundColorAttributeName] = [UIColor blackColor];
    dict[NSFontAttributeName] = [UIFont systemFontOfSize:10];
    
    // 禁用圖片渲染
    [childVC.tabBarItem setTitleTextAttributes:dict forState:UIControlStateNormal];
    childVC.tabBarItem.image = [[UIImage imageNamed:image] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
    childVC.tabBarItem.selectedImage = [[UIImage imageNamed:selectedImage] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];

    //字控制器圖片調整位置
    childVC.tabBarItem.imageInsets =  UIEdgeInsetsMake(5, 0, -5, 0);
    
    //    childVc.view.backgroundColor = RandomColor; // 這句代碼會自動加載主頁,消息准颓,發(fā)現(xiàn)棺妓,我四個控制器的view怜跑,但是view要在我們用的時候去提前加載
    
    //導航
    MineNavigationController *nav = [[MineNavigationController alloc] initWithRootViewController:childVC];
    //導航欄顏色
    nav.navigationBar.barTintColor = [UIColor whiteColor];
    
    [self addChildViewController:nav];
}

//二次點擊tabbar觸發(fā)刷新代理方法
- (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item
{
    // 判斷本次點擊的UITabBarItem是否和上次的一樣
    if (item == self.lastItem) { // 一樣就發(fā)出通知
        [[NSNotificationCenter defaultCenter] postNotificationName:@"LLTabBarDidClickNotification" object:nil userInfo:nil];
    }
    // 將這次點擊的UITabBarItem賦值給屬性
    self.lastItem = item;
    
}



//發(fā)布按鈕
- (void)plusBtnClick{
    
    //友盟點擊量統(tǒng)計
    [MobClick event:@"changwenfabu"];
    //push控制器
    MineNavigationController * nav = [(UITabBarController *)[UIApplication sharedApplication].keyWindow.rootViewController selectedViewController];
    
    if (SESSIONID.length>0) {
        //跳轉到發(fā)話題界面
        SendTopicViewController * SendTopic = [[SendTopicViewController alloc]init];
        SendTopic.hidesBottomBarWhenPushed = YES;
        SendTopic.type = @"UGC話題";
        [nav pushViewController:SendTopic animated:YES];
        
    }else{
        //跳到登陸界面
        LoginViewController * loginVc = [[LoginViewController alloc]init];
        loginVc.hidesBottomBarWhenPushed = YES;
        [nav pushViewController:loginVc animated:YES];
        
    }

    
  
}


#pragma mark ====================== 處理屏幕旋轉(在用峡眶,請不要刪)=========================
-(BOOL)shouldAutorotate{
   return [self.selectedViewController shouldAutorotate];
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
    return [self.selectedViewController supportedInterfaceOrientations];
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
    return [self.selectedViewController preferredInterfaceOrientationForPresentation];
}


@end

總結:這是我用過最好的中間凸出的tabbar了辫樱,希望大家喜歡(2017年6月13日)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市辉饱,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌缔逛,老刑警劉巖褐奴,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件歉糜,死亡現(xiàn)場離奇詭異匪补,居然都是意外死亡夯缺,警方通過查閱死者的電腦和手機踊兜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進店門捏境,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人贰剥,你說我怎么就攤上這事蚌成×菽螅” “怎么了?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵瓶盛,是天一觀的道長窒所。 經(jīng)常有香客問我鹉勒,道長,這世上最難降的妖魔是什么皮官? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任藻丢,我火速辦了婚禮摄乒,結果婚禮上悠反,老公的妹妹穿的比我還像新娘残黑。我一直安慰自己,他們只是感情好斋否,可當我...
    茶點故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布梨水。 她就那樣靜靜地躺著,像睡著了一般茵臭。 火紅的嫁衣襯著肌膚如雪疫诽。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天旦委,我揣著相機與錄音奇徒,去河邊找鬼。 笑死缨硝,一個胖子當著我的面吹牛逼龟,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼遣铝,長吁一口氣:“原來是場噩夢啊……” “哼瘫絮!你這毒婦竟也來了扁眯?” 一聲冷哼從身側響起命满,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤腋妙,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后济竹,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體丘跌,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡与殃,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年爽篷,在試婚紗的時候發(fā)現(xiàn)自己被綠了膨疏。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出实檀,到底是詐尸還是另有隱情签则,我是刑警寧澤,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布耘分,位于F島的核電站,受9級特大地震影響,放射性物質發(fā)生泄漏卜朗。R本人自食惡果不足惜逛万,卻給世界環(huán)境...
    茶點故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一忙上、第九天 我趴在偏房一處隱蔽的房頂上張望手形。 院中可真熱鬧,春花似錦、人聲如沸罢防。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽只厘。三九已至忘蟹,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間寝受,已是汗流浹背忙干。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留藤乙,地道東北人拴念。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓登失,卻偏偏與公主長得像,于是被迫代替她去往敵國和親敞曹。 傳聞我的和親對象是個殘疾皇子橄登,可洞房花燭夜當晚...
    茶點故事閱讀 44,592評論 2 353

推薦閱讀更多精彩內容