iOS自定義tabBar

hither發表於2017-12-13

在我們的專案中經常會自己自定義tabBar因為蘋果自帶的真的太醜了!也不滿足我們的專案需求。

好 開始行動吧!

先上圖看下我們最終實現的效果:

iOS自定義tabBar

繼承UItabBar自定義一個自己的tabBar

.h
#import <UIKit/UIKit.h>

@class HJTTabBar;
@protocol ZTTabBarDelegate <UITabBarDelegate>

@optional

- (void)tabBarDidClickPlusButton:(HJTTabBar *)tabBar;

@end

@interface HJTTabBar : UITabBar

@property (nonatomic, weak) id<ZTTabBarDelegate> myDelegate;

@end

複製程式碼
.m
#import "HJTTabBar.h"
#import "UIBarButtonItem+Extension.h"
#import "UIView+Extension.h"
@interface HJTTabBar ()

@property (nonatomic, weak) UIButton *plusBtn;

@end

@implementation HJTTabBar

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        UIButton *plusBtn = [[UIButton alloc] init];
        [plusBtn setBackgroundImage:[UIImage imageNamed:@"tabbar_compose_button"] forState:UIControlStateNormal];
        [plusBtn setBackgroundImage:[UIImage imageNamed:@"tabbar_compose_button_highlighted"] forState:UIControlStateHighlighted];
        [plusBtn setImage:[UIImage imageNamed:@"tabbar_compose_icon_add"] forState:UIControlStateNormal];
        [plusBtn setImage:[UIImage imageNamed:@"tabbar_compose_icon_add_highlighted"] forState:UIControlStateHighlighted];

        plusBtn.size = plusBtn.currentBackgroundImage.size;
        [plusBtn addTarget:self action:@selector(plusBtnClick) forControlEvents:UIControlEventTouchUpInside];
        [self addSubview:plusBtn];
        self.plusBtn = plusBtn;
    }
    return self;
}

/**
 *  加號按鈕點選
 */
- (void)plusBtnClick
{
    // 通知代理
    if ([self.delegate respondsToSelector:@selector(tabBarDidClickPlusButton:)]) {
        [self.myDelegate tabBarDidClickPlusButton:self];
    }
}

/**
 *  想要重新排布系統控制元件subview的佈局,推薦重寫layoutSubviews,在呼叫父類佈局後重新排布。
 */
- (void)layoutSubviews
{
    [super layoutSubviews];
    
    // 1.設定加號按鈕的位置
    self.plusBtn.centerX = self.width*0.5;
    self.plusBtn.centerY = self.height*0.5;
    
    // 2.設定其他tabbarButton的frame
    CGFloat tabBarButtonW = self.width / 5;
    CGFloat tabBarButtonIndex = 0;
    for (UIView *child in self.subviews) {
//UITabBarItem  UITabBarButton
        Class class = NSClassFromString(@"UITabBarItem  ");
        if ([child isKindOfClass:class]) {
            // 設定x
            child.x = tabBarButtonIndex * tabBarButtonW;
            // 設定寬度
            child.width = tabBarButtonW;
            // 增加索引
            tabBarButtonIndex++;
            if (tabBarButtonIndex == 2) {
                tabBarButtonIndex++;
            }
        }
    }
}

@end

複製程式碼

下面是Category:

UIView+Extension.h中:
#import <UIKit/UIKit.h>

@interface UIView (Extension)

@property (nonatomic, assign) CGFloat x;
@property (nonatomic, assign) CGFloat y;
@property (nonatomic, assign) CGFloat centerX;
@property (nonatomic, assign) CGFloat centerY;
@property (nonatomic, assign) CGFloat width;
@property (nonatomic, assign) CGFloat height;
@property (nonatomic, assign) CGSize size;
@property (nonatomic, assign) CGPoint origin;

@end
複製程式碼
UIView+Extension.m中:
#import "UIView+Extension.h"

@implementation UIView (Extension)

- (void)setX:(CGFloat)x
{
    CGRect frame = self.frame;
    frame.origin.x = x;
    self.frame = frame;
}

- (void)setY:(CGFloat)y
{
    CGRect frame = self.frame;
    frame.origin.y = y;
    self.frame = frame;
}

- (CGFloat)x
{
    return self.frame.origin.x;
}

- (CGFloat)y
{
    return self.frame.origin.y;
}

- (void)setCenterX:(CGFloat)centerX
{
    CGPoint center = self.center;
    center.x = centerX;
    self.center = center;
}

- (CGFloat)centerX
{
    return self.center.x;
}

- (void)setCenterY:(CGFloat)centerY
{
    CGPoint center = self.center;
    center.y = centerY;
    self.center = center;
}

- (CGFloat)centerY
{
    return self.center.y;
}

- (void)setWidth:(CGFloat)width
{
    CGRect frame = self.frame;
    frame.size.width = width;
    self.frame = frame;
}

- (void)setHeight:(CGFloat)height
{
    CGRect frame = self.frame;
    frame.size.height = height;
    self.frame = frame;
}

- (CGFloat)height
{
    return self.frame.size.height;
}

- (CGFloat)width
{
    return self.frame.size.width;
}

- (void)setSize:(CGSize)size
{
    CGRect frame = self.frame;
    frame.size = size;
    self.frame = frame;
}

- (CGSize)size
{
    return self.frame.size;
}

- (void)setOrigin:(CGPoint)origin
{
    CGRect frame = self.frame;
    frame.origin = origin;
    self.frame = frame;
}

- (CGPoint)origin
{
    return self.frame.origin;
}

@end
複製程式碼
UIBarButtonItem+Extension.h中:

#import <UIKit/UIKit.h>

@interface UIBarButtonItem (Extension)

+ (UIBarButtonItem *)itemWithTargat:(id)target action:(SEL)action image:(NSString *)image highImage:(NSString *)highImage;

@end
複製程式碼
UIBarButtonItem+Extension.m中:

#import "UIBarButtonItem+Extension.h"
#import "UIView+Extension.h"
@implementation UIBarButtonItem (Extension)

/**
 *  建立一個item
 *
 *  @param target    點選item後呼叫哪個物件的方法
 *  @param action    點選item後呼叫target的哪個方法
 *  @param image     圖片
 *  @param highImage 高亮的圖片
 *
 *  @return 建立完的item
 */
+ (UIBarButtonItem *)itemWithTargat:(id)target action:(SEL)action image:(NSString *)image highImage:(NSString *)highImage
{
    UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
    // 設定圖片
    [btn setBackgroundImage:[UIImage imageNamed:image] forState:UIControlStateNormal];
    [btn setBackgroundImage:[UIImage imageNamed:highImage] forState:UIControlStateHighlighted];
    // 設定尺寸
    btn.size = btn.currentBackgroundImage.size;
    [btn addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
    
    return [[UIBarButtonItem alloc] initWithCustomView:btn];
}

@end


複製程式碼

接下來我們就該在需要的地方使用自定義的tabBar了

  • 我是在UITabBarController中使用自定義的tabBar。
匯入#import "HJTTabBar.h"並遵循 HJTTabBarDelegate協議。
複製程式碼
在- (void)viewDidLoad 中實現下面程式碼:

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 新增子控制器
    [self addChildVc:[[FirstPageViewController alloc] init] title:@"首頁" image:@"tabbar_home" selectedImage:@"tabbar_home_selected"];
    [self addChildVc:[[CommunityViewController alloc] init] title:@"社群" image:@"tabbar_message_center" selectedImage:@"tabbar_message_center_selected"];
    [self addChildVc:[[MessageViewController alloc] init] title:@"訊息" image:@"tabbar_discover" selectedImage:@"tabbar_discover_selected"];
    [self addChildVc:[[ConsultViewController alloc] init] title:@"諮詢" image:@"tabbar_profile" selectedImage:@"tabbar_profile_selected"];
    
    HJTTabBar *tabBar = [[HJTTabBar alloc] init];
    
    //取消tabBar的透明效果
    tabBar.translucent = NO;
    tabBar.myDelegate = self;
    // KVC:如果要修系統的某些屬性,但被設為readOnly,就是用KVC,即setValue:forKey:。
    [self setValue:tabBar forKey:@"tabBar"];
      
}
複製程式碼

實現下面方法:

- (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];
    //    childVc.view.backgroundColor = RandomColor; // 這句程式碼會自動載入主頁,訊息,發現,我四個控制器的view,但是view要在我們用的時候去提前載入
    
    // 為子控制器包裝導航控制器
    UINavigationController *navigationVc = [[UINavigationController alloc] initWithRootViewController:childVc];
    // 新增子控制器
    [self addChildViewController:navigationVc];
}
複製程式碼

#pragma HJTTabBarDelegate
/**
 *  加號按鈕點選
 */
- (void)tabBarDidClickPlusButton:(HJTTabBar *)tabBar
{
    NSLog(@"+++");
}
複製程式碼

好了 完事!

相關文章