iOS 自定義選項卡-CYLTabBarController


正常的選項卡流程

cocoapods就不說了

創建一個CYLTabBarControllerConfig類

#import <Foundation/Foundation.h>
#import "CYLTabBarController.h"
@interface CYLTabBarControllerConfig : NSObject
@property (nonatomic, readonly, strong) CYLTabBarController *tabBarController;
@end
#import "CYLTabBarControllerConfig.h"
@import Foundation;
@import UIKit;
@interface CYLBaseNavigationController : UINavigationController
@end
@implementation CYLBaseNavigationController

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated {
    if (self.viewControllers.count > 0) {
        viewController.hidesBottomBarWhenPushed = YES;
    }
    [super pushViewController:viewController animated:animated];
}

@end

//View Controllers
#import "HandleViewController.h"
#import "EnquiriesViewController.h"
#import "ConsultViewController.h"
#import "ManagerViewController.h"
#import "ErectViewController.h"

@interface CYLTabBarControllerConfig ()

@property (nonatomic, readwrite, strong) CYLTabBarController *tabBarController;

@end

@implementation CYLTabBarControllerConfig
/**
 *  lazy load tabBarController
 *
 *  @return CYLTabBarController
 */
- (CYLTabBarController *)tabBarController {
    if (_tabBarController == nil) {
        HandleViewController *firstViewController = [[HandleViewController alloc] init];
        UIViewController *firstNavigationController = [[CYLBaseNavigationController alloc]
                                                       initWithRootViewController:firstViewController];
        
        EnquiriesViewController *secondViewController = [[EnquiriesViewController alloc] init];
        UIViewController *secondNavigationController = [[CYLBaseNavigationController alloc]
                                                        initWithRootViewController:secondViewController];
        /**
         *  選項卡右上角的數字
         */
//        secondNavigationController.tabBarItem.badgeValue = @"10";
        
        ConsultViewController *thirdViewController = [[ConsultViewController alloc] init];
        UIViewController *thirdNavigationController = [[CYLBaseNavigationController alloc]
                                                       initWithRootViewController:thirdViewController];
        
        ManagerViewController *fourthViewController = [[ManagerViewController alloc] init];
        UIViewController *fourthNavigationController = [[CYLBaseNavigationController alloc]
                                                        initWithRootViewController:fourthViewController];
        ErectViewController *fifthViewControll = [[ErectViewController alloc]init];
        UIViewController *fifthNavigationController = [[CYLBaseNavigationController alloc]initWithRootViewController:fifthViewControll];

        CYLTabBarController *tabBarController = [[CYLTabBarController alloc] init];
        
        /**
         * 以下兩行代碼目的在於手動設置讓TabBarItem只顯示圖標,不顯示文字,並讓圖標垂直居中。
         * 等效於在`-setUpTabBarItemsAttributesForController`方法中不傳`CYLTabBarItemTitle`字段。
         * 更推薦后一種做法。
         */
        //tabBarController.imageInsets = UIEdgeInsetsMake(4.5, 0, -4.5, 0);
        //tabBarController.titlePositionAdjustment = UIOffsetMake(0, MAXFLOAT);
        
        // 在`-setViewControllers:`之前設置TabBar的屬性,設置TabBarItem的屬性,包括 title、Image、selectedImage。
        [self setUpTabBarItemsAttributesForController:tabBarController];
        
        [tabBarController setViewControllers:@[
                                               firstNavigationController,
                                               secondNavigationController,
                                               thirdNavigationController,
                                               fourthNavigationController,
                                               fifthNavigationController
                                               ]];
        // 更多TabBar自定義設置:比如:tabBarItem 的選中和不選中文字和背景圖片屬性、tabbar 背景圖片屬性
        [self customizeTabBarAppearance:tabBarController];
        _tabBarController = tabBarController;
    }
    return _tabBarController;
}

/**
 *  在`-setViewControllers:`之前設置TabBar的屬性,設置TabBarItem的屬性,包括 title、Image、selectedImage。
 */
- (void)setUpTabBarItemsAttributesForController:(CYLTabBarController *)tabBarController {
    
    NSDictionary *dict1 = @{
                            CYLTabBarItemTitle : @"訂單處理",
                            CYLTabBarItemImage : @"tab_dingdanchuli",
                            CYLTabBarItemSelectedImage : @"tab_dingdanchuli_s",
                            };
    NSDictionary *dict2 = @{
                            CYLTabBarItemTitle : @"訂單查詢",
                            CYLTabBarItemImage : @"tab_dingdanchaxun",
                            CYLTabBarItemSelectedImage : @"tab_dingdanchaxun_s",
                            };
    NSDictionary *dict3 = @{
                            CYLTabBarItemTitle : @"咨詢",
                            CYLTabBarItemImage : @"tab_xiaoxi",
                            CYLTabBarItemSelectedImage : @"tab_xiaoxi_s",
                            };
    NSDictionary *dict4 = @{
                            CYLTabBarItemTitle : @"門店管理",
                            CYLTabBarItemImage : @"tab_mendianguanli",
                            CYLTabBarItemSelectedImage : @"tab_mendianguanli_s"
                            };
    NSDictionary *dict5 = @{
                            CYLTabBarItemTitle : @"設置",
                            CYLTabBarItemImage : @"tab_shezhi",
                            CYLTabBarItemSelectedImage : @"tab_shezhi_s"
                            };
    NSArray *tabBarItemsAttributes = @[
                                       dict1,
                                       dict2,
                                       dict3,
                                       dict4,
                                       dict5
                                       ];
    tabBarController.tabBarItemsAttributes = tabBarItemsAttributes;
}

/**
 *  更多TabBar自定義設置:比如:tabBarItem 的選中和不選中文字和背景圖片屬性、tabbar 背景圖片屬性
 */
- (void)customizeTabBarAppearance:(CYLTabBarController *)tabBarController {
    // Customize UITabBar height
    // 自定義 TabBar 高度
//     tabBarController.tabBarHeight = 80.f;
    
    // set the text color for unselected state
    // 普通狀態下的文字屬性
    NSMutableDictionary *normalAttrs = [NSMutableDictionary dictionary];
    normalAttrs[NSForegroundColorAttributeName] = [UIColor grayColor];
    
    // set the text color for selected state
    // 選中狀態下的文字屬性
    NSMutableDictionary *selectedAttrs = [NSMutableDictionary dictionary];
    selectedAttrs[NSForegroundColorAttributeName] = RGBColor(72, 199, 22);
    
    // set the text Attributes
    // 設置文字屬性
    UITabBarItem *tabBar = [UITabBarItem appearance];
    [tabBar setTitleTextAttributes:normalAttrs forState:UIControlStateNormal];
    [tabBar setTitleTextAttributes:selectedAttrs forState:UIControlStateSelected];
    
    // Set the dark color to selected tab (the dimmed background)
    // TabBarItem選中后的背景顏色
    // [self customizeTabBarSelectionIndicatorImage];
    
    // update TabBar when TabBarItem width did update
    // If your app need support UIDeviceOrientationLandscapeLeft or UIDeviceOrientationLandscapeRight,
    // remove the comment '//'
    // 如果你的App需要支持橫豎屏,請使用該方法移除注釋 '//'
    // [self updateTabBarCustomizationWhenTabBarItemWidthDidUpdate];
    
    // set the bar shadow image
    // This shadow image attribute is ignored if the tab bar does not also have a custom background image.So at least set somthing.
    [[UITabBar appearance] setBackgroundImage:[[UIImage alloc] init]];
    [[UITabBar appearance] setBackgroundColor:[UIColor whiteColor]];
    [[UITabBar appearance] setShadowImage:[UIImage imageNamed:@"tapbar_top_line"]];
    
    // set the bar background image
    // 設置背景圖片
    // UITabBar *tabBarAppearance = [UITabBar appearance];
    // [tabBarAppearance setBackgroundImage:[UIImage imageNamed:@"tabbar_background"]];
    
    // remove the bar system shadow image
    // 去除 TabBar 自帶的頂部陰影
    // [[UITabBar appearance] setShadowImage:[[UIImage alloc] init]];
}

- (void)updateTabBarCustomizationWhenTabBarItemWidthDidUpdate {
    void (^deviceOrientationDidChangeBlock)(NSNotification *) = ^(NSNotification *notification) {
        UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
        if ((orientation == UIDeviceOrientationLandscapeLeft) || (orientation == UIDeviceOrientationLandscapeRight)) {
            NSLog(@"Landscape Left or Right !");
        } else if (orientation == UIDeviceOrientationPortrait){
            NSLog(@"Landscape portrait!");
        }
        [self customizeTabBarSelectionIndicatorImage];
    };
    [[NSNotificationCenter defaultCenter] addObserverForName:CYLTabBarItemWidthDidChangeNotification
                                                      object:nil
                                                       queue:[NSOperationQueue mainQueue]
                                                  usingBlock:deviceOrientationDidChangeBlock];
}

- (void)customizeTabBarSelectionIndicatorImage {
    ///Get initialized TabBar Height if exists, otherwise get Default TabBar Height.
    UITabBarController *tabBarController = [self cyl_tabBarController] ?: [[UITabBarController alloc] init];
    CGFloat tabBarHeight = tabBarController.tabBar.frame.size.height;
    CGSize selectionIndicatorImageSize = CGSizeMake(CYLTabBarItemWidth, tabBarHeight);
    //Get initialized TabBar if exists.
    UITabBar *tabBar = [self cyl_tabBarController].tabBar ?: [UITabBar appearance];
    [tabBar setSelectionIndicatorImage:
     [[self class] imageWithColor:[UIColor redColor]
                             size:selectionIndicatorImageSize]];
}

+ (UIImage *)imageWithColor:(UIColor *)color size:(CGSize)size {
    if (!color || size.width <= 0 || size.height <= 0) return nil;
    CGRect rect = CGRectMake(0.0f, 0.0f, size.width + 1, size.height);
    UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetFillColorWithColor(context, color.CGColor);
    CGContextFillRect(context, rect);
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return image;
}

- (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

 

 

 

 

另外還有自定義的加號按鈕

要創建一個CYLPlusButton的類不要忘了加上CYLPlusButtonSubclassing協議

#import <CYLTabBarController/CYLTabBarController.h>


@interface CYLPlusButtonSubclass : CYLPlusButton<CYLPlusButtonSubclassing,UIActionSheetDelegate>


@end
#import "CYLPlusButtonSubclass.h"
#import <CYLTabBarController.h>

@implementation CYLPlusButtonSubclass

+(void)load{
    [super registerSubclass];
}

- (instancetype)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        self.titleLabel.textAlignment = NSTextAlignmentCenter;
        self.adjustsImageWhenHighlighted = NO;
        
    }
    return self;
}
//上下結構的 button
- (void)layoutSubviews {
    [super layoutSubviews];
    
    // 控件大小,間距大小
    CGFloat const imageViewEdgeWidth   = self.bounds.size.width * 0.7;
    CGFloat const imageViewEdgeHeight  = imageViewEdgeWidth * 0.9;
    CGFloat const centerOfView    = self.bounds.size.width * 0.5;
    CGFloat const labelLineHeight = self.titleLabel.font.lineHeight;
    CGFloat const verticalMarginT = self.bounds.size.height - labelLineHeight - imageViewEdgeWidth;
    CGFloat const verticalMargin  = verticalMarginT / 2;
    
    // imageView 和 titleLabel 中心的 Y 值
    CGFloat const centerOfImageView  = verticalMargin + imageViewEdgeWidth * 0.5;
    CGFloat const centerOfTitleLabel = imageViewEdgeWidth  + verticalMargin * 2 + labelLineHeight * 0.5 + 5;
    
    //imageView position 位置
    self.imageView.bounds = CGRectMake(0, 0, imageViewEdgeWidth, imageViewEdgeHeight);
    self.imageView.center = CGPointMake(centerOfView, centerOfImageView);
    
    //title position 位置
    self.titleLabel.bounds = CGRectMake(0, 0, self.bounds.size.width, labelLineHeight);
    self.titleLabel.center = CGPointMake(centerOfView, centerOfTitleLabel);
}
/*
 *
 Create a custom UIButton with title and add it to the center of our tab bar
 *
 */
+ (id)plusButton {
    CYLPlusButtonSubclass *button = [[CYLPlusButtonSubclass alloc] init];
    UIImage *buttonImage = [UIImage imageNamed:@"post_normal"];
    [button setImage:buttonImage forState:UIControlStateNormal];
    [button setTitle:@"發布" forState:UIControlStateNormal];
    [button setTitleColor:[UIColor grayColor] forState:UIControlStateNormal];
    
    [button setTitle:@"選中" forState:UIControlStateSelected];
    [button setTitleColor:[UIColor blueColor] forState:UIControlStateSelected];
    
    button.titleLabel.font = [UIFont systemFontOfSize:9.5];
    [button sizeToFit]; // or set frame in this way `button.frame = CGRectMake(0.0, 0.0, 250, 100);`
    [button addTarget:button action:@selector(clickPublish) forControlEvents:UIControlEventTouchUpInside];
    return button;
}

/*
 *
 Create a custom UIButton without title and add it to the center of our tab bar
 *
 */
//+ (id)plusButton
//{
//
//    UIImage *buttonImage = [UIImage imageNamed:@"hood.png"];
//    UIImage *highlightImage = [UIImage imageNamed:@"hood-selected.png"];
//
//    CYLPlusButtonSubclass* button = [CYLPlusButtonSubclass buttonWithType:UIButtonTypeCustom];
//
//    button.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleTopMargin;
//    button.frame = CGRectMake(0.0, 0.0, buttonImage.size.width, buttonImage.size.height);
//    [button setBackgroundImage:buttonImage forState:UIControlStateNormal];
//    [button setBackgroundImage:highlightImage forState:UIControlStateHighlighted];
//    [button addTarget:button action:@selector(clickPublish) forControlEvents:UIControlEventTouchUpInside];
//
//    return button;
//}
- (void)clickPublish {
    CYLTabBarController *tabBarController = [self cyl_tabBarController];
    UIViewController *viewController = tabBarController.selectedViewController;
    UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:nil
                                                             delegate:nil
                                                    cancelButtonTitle:@"取消"
                                               destructiveButtonTitle:nil
                                                    otherButtonTitles:@"拍照", @"從相冊選取", @"淘寶一鍵轉賣", nil];
    [actionSheet showInView:viewController.view];
    NSLog(@"發布");
}
#pragma mark - CYLPlusButtonSubclassing
//+ (UIViewController *)plusChildViewController {
//    UIViewController *plusChildViewController = [[UIViewController alloc] init];
//    plusChildViewController.view.backgroundColor = [UIColor redColor];
//    plusChildViewController.navigationItem.title = @"PlusChildViewController";
//    UIViewController *plusChildNavigationController = [[UINavigationController alloc]
//                                                   initWithRootViewController:plusChildViewController];
//    return plusChildNavigationController;
//}
//
+ (NSUInteger)indexOfPlusButtonInTabBar {
    return 5;
}
+ (CGFloat)multiplerInCenterY {
    return  0.3;
}

如果正常按鈕數目是奇數的話 要實現

+ (NSUInteger)indexOfPlusButtonInTabBar {
    return 5;
}

如何調整、自定義 PlusButton 與其它 TabBarItem 的寬度?

CYLTabBarController 規定:

 TabBarItem 寬度 =  ( TabBar 總寬度 -  PlusButton 寬度  ) / (TabBarItem 個數)

所以想自定義寬度,只需要修改 PlusButton 的寬度即可。

比如你就可以在 Demo中的 CYLPlusButtonSubclass.m 類里:

[button sizeToFit]

改為

button.frame = CGRectMake(0.0, 0.0, 250, 100);

---------------

如果要把加號按鈕做成跟其他按鈕的點擊效果一樣的話需要同時實現這兩個方法

+ (UIViewController *)plusChildViewController {
    UIViewController *plusChildViewController = [[UIViewController alloc] init];
    plusChildViewController.view.backgroundColor = [UIColor redColor];
    plusChildViewController.navigationItem.title = @"PlusChildViewController";
    UIViewController *plusChildNavigationController = [[UINavigationController alloc]
                                                   initWithRootViewController:plusChildViewController];
    return plusChildNavigationController;
}

+ (NSUInteger)indexOfPlusButtonInTabBar {
    return 5;
}

 

之前不知道怎么回事,出了些莫名其妙的問題。。記錄下

前人種樹后人乘涼啊!感謝原作作者

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM