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日)