1. 程式人生 > >UITabBar自定義方式三(中間有按鈕)

UITabBar自定義方式三(中間有按鈕)

1.MainTableViewController

#import "MainTabBarViewController.h"
#import "IWHomeViewController.h"
#import "IWMessageViewController.h"
#import "IWMeViewController.h"
#import "IWDiscoverViewController.h"
#import "UIImage+MJ.h"
#import "MyTabBar.h"

@interface MainTabBarViewController () <IWTabBarDelegate>
/**
 *  自定義的tabbar
 */
@property (nonatomic, weak) MyTabBar *customTabBar;
@end

@implementation MainTabBarViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    // 初始化tabbar
    [self setupTabbar];
    
    // 初始化所有的子控制器
    [self setupAllChildViewControllers];
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    
    // 刪除系統自動生成的UITabBarButton
    for (UIView *child in self.tabBar.subviews) {
        if ([child isKindOfClass:[UIControl class]]) {
            [child removeFromSuperview];
        }
    }
}

/**
 *  初始化tabbar
 */
- (void)setupTabbar
{
    MyTabBar *customTabBar = [[MyTabBar alloc] init];
    customTabBar.frame = self.tabBar.bounds;
    customTabBar.delegate = self;
    [self.tabBar addSubview:customTabBar];
    self.customTabBar = customTabBar;
}

/**
 *  監聽tabbar按鈕的改變
 *  @param from   原來選中的位置
 *  @param to     最新選中的位置
 */
- (void)tabBar:(MyTabBar *)tabBar didSelectedButtonFrom:(int)from to:(int)to
{
    self.selectedIndex = to;
}

/**
 *  初始化所有的子控制器
 */
- (void)setupAllChildViewControllers
{
    // 1.首頁
    IWHomeViewController *home = [[IWHomeViewController alloc] init];
    [self setupChildViewController:home title:@"首頁" imageName:@"tabbar_home" selectedImageName:@"tabbar_home_selected"];
    
    // 2.訊息
    IWMessageViewController *message = [[IWMessageViewController alloc] init];
    [self setupChildViewController:message title:@"訊息" imageName:@"tabbar_message_center" selectedImageName:@"tabbar_message_center_selected"];
    
    // 3.廣場
    IWDiscoverViewController *discover = [[IWDiscoverViewController alloc] init];
    [self setupChildViewController:discover title:@"廣場" imageName:@"tabbar_discover" selectedImageName:@"tabbar_discover_selected"];
    
    // 4.我
    IWMeViewController *me = [[IWMeViewController alloc] init];
    [self setupChildViewController:me title:@"我" imageName:@"tabbar_profile" selectedImageName:@"tabbar_profile_selected"];
}

/**
 *  初始化一個子控制器
 *
 *  @param childVc           需要初始化的子控制器
 *  @param title             標題
 *  @param imageName         圖示
 *  @param selectedImageName 選中的圖示
 */
- (void)setupChildViewController:(UIViewController *)childVc title:(NSString *)title imageName:(NSString *)imageName selectedImageName:(NSString *)selectedImageName
{
    // 1.設定控制器的屬性
    childVc.title = title;
    // 設定圖示
    childVc.tabBarItem.image = [UIImage imageWithName:imageName];
    // 設定選中的圖示
    UIImage *selectedImage = [UIImage imageWithName:selectedImageName];
    if (iOS7) {
        childVc.tabBarItem.selectedImage = [selectedImage imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
    } else {
        childVc.tabBarItem.selectedImage = selectedImage;
    }
    
    // 2.包裝一個導航控制器
    UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:childVc];
    [self addChildViewController:nav];
    
    // 3.新增tabbar內部的按鈕
    [self.customTabBar addTabBarButtonWithItem:childVc.tabBarItem];
}

2.MyTabBar
#import <UIKit/UIKit.h>

@class MyTabBar;

@protocol IWTabBarDelegate <NSObject>

@optional
- (void)tabBar:(MyTabBar *)tabBar didSelectedButtonFrom:(int)from to:(int)to;

@end

@interface MyTabBar : UIView
- (void)addTabBarButtonWithItem:(UITabBarItem *)item;

@property (nonatomic, weak) id<IWTabBarDelegate> delegate;

@end





#import "MyTabBar.h"
#import "MyTabBarButton.h"

@interface MyTabBar()
@property (nonatomic, strong) NSMutableArray *tabBarButtons;
@property (nonatomic, weak) UIButton *plusButton;
@property (nonatomic, weak) MyTabBarButton *selectedButton;
@end

@implementation MyTabBar

- (NSMutableArray *)tabBarButtons
{
    if (_tabBarButtons == nil) {
        _tabBarButtons = [NSMutableArray array];
    }
    return _tabBarButtons;
}

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        if (!iOS7) { // 非iOS7下,設定tabbar的背景
            self.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageWithName:@"tabbar_background"]];
        }
        
        // 新增一個加號按鈕
        UIButton *plusButton = [UIButton buttonWithType:UIButtonTypeCustom];
        [plusButton setBackgroundImage:[UIImage imageWithName:@"tabbar_compose_button"] forState:UIControlStateNormal];
        [plusButton setBackgroundImage:[UIImage imageWithName:@"tabbar_compose_button_highlighted"] forState:UIControlStateHighlighted];
        [plusButton setImage:[UIImage imageWithName:@"tabbar_compose_icon_add"] forState:UIControlStateNormal];
        [plusButton setImage:[UIImage imageWithName:@"tabbar_compose_icon_add_highlighted"] forState:UIControlStateHighlighted];
        plusButton.bounds = CGRectMake(0, 0, plusButton.currentBackgroundImage.size.width, plusButton.currentBackgroundImage.size.height);
        [self addSubview:plusButton];
        self.plusButton = plusButton;
    }
    return self;
}

- (void)addTabBarButtonWithItem:(UITabBarItem *)item
{
    // 1.建立按鈕
    MyTabBarButton *button = [[MyTabBarButton alloc] init];
    [self addSubview:button];
    // 新增按鈕到陣列中
    [self.tabBarButtons addObject:button];
    
    // 2.設定資料
    button.item = item;
    
    // 3.監聽按鈕點選
    [button addTarget:self action:@selector(buttonClick:) forControlEvents:UIControlEventTouchDown];
    
    // 4.預設選中第0個按鈕
    if (self.tabBarButtons.count == 1) {
        [self buttonClick:button];
    }
}

/**
 *  監聽按鈕點選
 */
- (void)buttonClick:(MyTabBarButton *)button
{
    // 1.通知代理
    if ([self.delegate respondsToSelector:@selector(tabBar:didSelectedButtonFrom:to:)]) {
        [self.delegate tabBar:self didSelectedButtonFrom:self.selectedButton.tag to:button.tag];
    }
    
    // 2.設定按鈕的狀態
    self.selectedButton.selected = NO;
    button.selected = YES;
    self.selectedButton = button;
}

- (void)layoutSubviews
{
    [super layoutSubviews];
    
    // 調整加號按鈕的位置
    CGFloat h = self.frame.size.height;
    CGFloat w = self.frame.size.width;
    self.plusButton.center = CGPointMake(w * 0.5, h * 0.5);
    
    // 按鈕的frame資料
    CGFloat buttonH = h;
    CGFloat buttonW = w / self.subviews.count;
    CGFloat buttonY = 0;
    
    for (int index = 0; index<self.tabBarButtons.count; index++) {
        // 1.取出按鈕
        MyTabBarButton *button = self.tabBarButtons[index];
        
        // 2.設定按鈕的frame
        CGFloat buttonX = index * buttonW;
        if (index > 1) {
            buttonX += buttonW;
        }
        button.frame = CGRectMake(buttonX, buttonY, buttonW, buttonH);
        
        // 3.繫結tag
        button.tag = index;
    }
}
@end
3.MyTabBarButton
#import <UIKit/UIKit.h>

@interface MyTabBarButton : UIButton
@property (nonatomic, strong) UITabBarItem *item;
@end


// 圖示的比例
#define IWTabBarButtonImageRatio 0.6

// 按鈕的預設文字顏色
#define  IWTabBarButtonTitleColor (iOS7 ? [UIColor blackColor] : [UIColor whiteColor])
// 按鈕的選中文字顏色
#define  IWTabBarButtonTitleSelectedColor (iOS7 ? IWColor(234, 103, 7) : IWColor(248, 139, 0))

#import "MyTabBarButton.h"
#import "MyBadgeButton.h"

@interface MyTabBarButton()
/**
 *  提醒數字
 */
@property (nonatomic, weak) MyBadgeButton *badgeButton;
@end

@implementation MyTabBarButton

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // 圖示居中
        self.imageView.contentMode = UIViewContentModeCenter;
        // 文字居中
        self.titleLabel.textAlignment = NSTextAlignmentCenter;
        // 字型大小
        self.titleLabel.font = [UIFont systemFontOfSize:11];
        // 文字顏色
        [self setTitleColor:IWTabBarButtonTitleColor forState:UIControlStateNormal];
        [self setTitleColor:IWTabBarButtonTitleSelectedColor forState:UIControlStateSelected];
        
        if (!iOS7) { // 非iOS7下,設定按鈕選中時的背景
            [self setBackgroundImage:[UIImage imageWithName:@"tabbar_slider"] forState:UIControlStateSelected];
        }
        
        // 新增一個提醒數字按鈕
        MyBadgeButton *badgeButton = [[MyBadgeButton alloc] init];
        badgeButton.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleBottomMargin;
        [self addSubview:badgeButton];
        self.badgeButton = badgeButton;
    }
    return self;
}

// 重寫去掉高亮狀態
- (void)setHighlighted:(BOOL)highlighted {}

// 內部圖片的frame
- (CGRect)imageRectForContentRect:(CGRect)contentRect
{
    CGFloat imageW = contentRect.size.width;
    CGFloat imageH = contentRect.size.height * IWTabBarButtonImageRatio;
    return CGRectMake(0, 0, imageW, imageH);
}

// 內部文字的frame
- (CGRect)titleRectForContentRect:(CGRect)contentRect
{
    CGFloat titleY = contentRect.size.height * IWTabBarButtonImageRatio;
    CGFloat titleW = contentRect.size.width;
    CGFloat titleH = contentRect.size.height - titleY;
    return CGRectMake(0, titleY, titleW, titleH);
}

// 設定item
- (void)setItem:(UITabBarItem *)item
{
    _item = item;
    
    // KVO 監聽屬性改變
    [item addObserver:self forKeyPath:@"badgeValue" options:0 context:nil];
    [item addObserver:self forKeyPath:@"title" options:0 context:nil];
    [item addObserver:self forKeyPath:@"image" options:0 context:nil];
    [item addObserver:self forKeyPath:@"selectedImage" options:0 context:nil];
    
    [self observeValueForKeyPath:nil ofObject:nil change:nil context:nil];
}

- (void)dealloc
{
    [self.item removeObserver:self forKeyPath:@"badgeValue"];
    [self.item removeObserver:self forKeyPath:@"title"];
    [self.item removeObserver:self forKeyPath:@"image"];
    [self.item removeObserver:self forKeyPath:@"selectedImage"];
}

/**
 *  監聽到某個物件的屬性改變了,就會呼叫
 *
 *  @param keyPath 屬性名
 *  @param object  哪個物件的屬性被改變
 *  @param change  屬性發生的改變
 */
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    // 設定文字
    [self setTitle:self.item.title forState:UIControlStateSelected];
    [self setTitle:self.item.title forState:UIControlStateNormal];
    
    // 設定圖片
    [self setImage:self.item.image forState:UIControlStateNormal];
    [self setImage:self.item.selectedImage forState:UIControlStateSelected];
    
    // 設定提醒數字
    self.badgeButton.badgeValue = self.item.badgeValue;
    
    // 設定提醒數字的位置
    CGFloat badgeY = 5;
    CGFloat badgeX = self.frame.size.width - self.badgeButton.frame.size.width - 10;
    CGRect badgeF = self.badgeButton.frame;
    badgeF.origin.x = badgeX;
    badgeF.origin.y = badgeY;
    self.badgeButton.frame = badgeF;
}
@end


4.MyBadgeButton提醒數字
@interface MyBadgeButton : UIButton
@property (nonatomic, copy) NSString *badgeValue;
@end




#import "MyBadgeButton.h"

@implementation MyBadgeButton

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        self.hidden = YES;
        self.userInteractionEnabled = NO;
        [self setBackgroundImage:[UIImage resizedImageWithName:@"main_badge"] forState:UIControlStateNormal];
        self.titleLabel.font = [UIFont systemFontOfSize:11];
    }
    return self;
}

- (void)setBadgeValue:(NSString *)badgeValue
{
#warning copy
//    _badgeValue = badgeValue;
    _badgeValue = [badgeValue copy];
    
    if (badgeValue) {
        self.hidden = NO;
        // 設定文字
        [self setTitle:badgeValue forState:UIControlStateNormal];
        
        // 設定frame
        CGRect frame = self.frame;
        CGFloat badgeH = self.currentBackgroundImage.size.height;
        CGFloat badgeW = self.currentBackgroundImage.size.width;
        if (badgeValue.length > 1) {
            // 文字的尺寸
            CGSize badgeSize = [badgeValue sizeWithFont:self.titleLabel.font];
            badgeW = badgeSize.width + 10;
        }
        frame.size.width = badgeW;
        frame.size.height = badgeH;
        self.frame = frame;
    } else {
        self.hidden = YES;
    }
}

@end



Demo連結: http://pan.baidu.com/s/1qW9RjA0 密碼: s22h