IOS自定義TabBar(OC和Swift)

OC Demo : 傳送門
SwfitDemo : 傳送門

效果圖

滑動隱藏Tabbar.gif
自定義小紅點.gif
凸起來的加號按鈕tabbar.gif
淘寶按鈕tabbar.gif
動畫按鈕tabbar.gif
京東起彈Tabbar.gif

思路一、(類似閑魚點擊跳轉其他界面的)
1、使用KVC:如果要修系統的某些屬性,但被設為readOnly,就是用KVC,即setValue:>forKey
2、創建比需要顯示UITabBarController的控制器少一個的控制器的viewControllers
3、自定義一個tabBar、使用layoutSubviews或init(frame: CGRect)、定位到自己喜歡的位置
4、在自定義tabBar創建一個按鈕、使用代理可以跳轉其他的界面

OC代碼
CustomTabBarViewController.h

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface CustomTabBarViewController : UITabBarController

@end

NS_ASSUME_NONNULL_END

CustomTabBarViewController.m

#import "CustomTabBarViewController.h"
#import "Demo1ViewController.h"
#import "Demo2ViewController.h"
#import "Demo3ViewController.h"
#import "Demo4ViewController.h"
#import "Demo5ViewController.h"
#import "SimpleCustomDemoViewController.h"
#import "CustomTabBar.h"

@interface CustomTabBarViewController ()<UITabBarControllerDelegate, CustomTabBarDelegate>

@property (strong, nonatomic) CustomTabBar *customTabBar;

@end

@implementation CustomTabBarViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    CustomTabBar *tabBar = [[CustomTabBar alloc] init];
    //取消tabBar的透明效果
    tabBar.translucent = NO;
    // 設置tabBar的代理
    tabBar.myDelegate = self;
    // KVC:如果要修系統的某些屬性,但被設為readOnly,就是用KVC,即setValue:forKey:。
    [self setValue:tabBar forKey:@"tabBar"];
    self.customTabBar = tabBar;
    
    [self tabBarControllerAddChildViewController];
}

-(void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];
    self.navigationController.navigationBarHidden = YES;
}

# pragma mark - 添加子類的數據
- (void)tabBarControllerAddChildViewController
{
    NSArray *classControllers = [NSArray array];
    classControllers = @[@"Demo1ViewController", @"Demo2ViewController", @"Demo4ViewController", @"Demo5ViewController"];
    NSArray *titles = @[@"首頁", @"附近", @"聊天", @"我的"];
    NSArray *normalImages = @[@"home_normal", @"mycity_normal", @"message_normal", @"account_normal"];
    NSArray *selectImages = @[@"home_highlight", @"mycity_highlight", @"message_highlight", @"account_highlight"];
    
    [self TabbarControllerAddSubViewsControllers:classControllers addTitleArray:titles addNormalImagesArray:normalImages addSelectImageArray:selectImages];
}


# pragma mark - 初始化Tabbar里面的元素
- (void)TabbarControllerAddSubViewsControllers:(NSArray *)classControllersArray addTitleArray:(NSArray *)titleArray addNormalImagesArray:(NSArray *)normalImagesArray addSelectImageArray:(NSArray *)selectImageArray
{
    NSMutableArray *conArr = [NSMutableArray array];
    
    for (int i = 0; i < classControllersArray.count; i++) {
        
        Class cts = NSClassFromString(classControllersArray[I]);
        UIViewController *vc = [[cts alloc] init];
        UINavigationController *naVC = [[UINavigationController alloc] initWithRootViewController:vc];
        [conArr addObject:naVC];
        
        UIImage *normalImage = [[UIImage imageNamed:normalImagesArray[i]] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
        UIImage *selectImage = [[UIImage imageNamed:selectImageArray[i]] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
        
        vc.tabBarItem = [[UITabBarItem alloc] initWithTitle:titleArray[i] image:normalImage selectedImage:selectImage];
        vc.tabBarItem.tag = I;

    }
    
    self.viewControllers = conArr;
    self.tabBar.tintColor = [UIColor colorWithRed:255.0/255 green:204.0/255 blue:13.0/255 alpha:1];
    self.tabBar.translucent = NO;
    
    self.delegate = self;
}

#pragma TaoBaoCustomTabBar
/**
 *  點擊了加號按鈕
 */
- (void)tabBarDidClickPlusButton:(CustomTabBar *)tabBar
{
    /**
     definesPresentationContext這一屬性決定了那個父控制器的View,
     將會以優先于UIModalPresentationCurrentContext這種呈現方式來展現自己的View。
     如果沒有父控制器設置這一屬性,那么展示的控制器將會是根視圖控制器
     
     modalPresentationStyle可以設置模態是否隱藏
     
     */
    
    tabBar.plusButton.selected = YES;
    
    SimpleCustomDemoViewController *vc = [SimpleCustomDemoViewController new];
    self.definesPresentationContext = YES;
    vc.view.backgroundColor = [UIColor clearColor];
    vc.modalPresentationStyle = UIModalPresentationOverCurrentContext;
    [self presentViewController:vc animated:YES completion:nil];
}

# pragma mark - UITabBarControllerDelegate
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController
{
    self.customTabBar.plusButton.selected = NO;
    return YES;
}

@end

CustomTabBar.h

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@class CustomTabBar;

@protocol CustomTabBarDelegate <UITabBarDelegate>

@optional
// 當點擊自定義tabbar的時候
- (void)tabBarDidClickPlusButton:(CustomTabBar *)tabBar;

@end


@interface CustomTabBar : UITabBar

@property (nonatomic, strong) UIButton *plusButton;

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

@end

NS_ASSUME_NONNULL_END

CustomTabBar.m

#import "CustomTabBar.h"

@interface CustomTabBar ()

@end

@implementation CustomTabBar

# pragma mark - 賴加載
- (UIButton *)plusButton
{
    if (_plusButton == nil) {
        _plusButton = [[UIButton alloc] init];
        [_plusButton setImage:[UIImage imageNamed:@"post_normal"] forState:UIControlStateNormal];
        [_plusButton setImage:[UIImage imageNamed:@"post_normal"] forState:UIControlStateHighlighted];
       
        _plusButton.titleLabel.font = [UIFont systemFontOfSize:11];
        [_plusButton setTitle:@"發布" forState:UIControlStateNormal];
        [_plusButton setTitle:@"發布" forState:UIControlStateHighlighted];
        [_plusButton setTitleColor:[UIColor grayColor] forState:UIControlStateNormal];
//        [_plusButton setTitleColor:[UIColor colorWithRed:255.0/255 green:204.0/255 blue:13.0/255 alpha:1] forState:UIControlStateSelected];
       
        UIImage *buttonImg = [_plusButton imageForState:UIControlStateNormal];
        CGFloat titleWidth = [_plusButton.titleLabel.text sizeWithAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[UIFont boldSystemFontOfSize:11],NSFontAttributeName, nil]].width;
        [_plusButton setTitleEdgeInsets:UIEdgeInsetsMake(buttonImg.size.height, -buttonImg.size.width, -15, 0)];
        [_plusButton setImageEdgeInsets:UIEdgeInsetsMake(-15, 0, 0, -titleWidth)];
        
        _plusButton.frame = CGRectMake(0, 0, _plusButton.imageView.image.size.width, _plusButton.imageView.image.size.height + 40);
        [_plusButton addTarget:self action:@selector(respondsToPlusButton) forControlEvents:UIControlEventTouchUpInside];
    }
    return _plusButton;
}

# pragma mark - CustomTabBarDelegate
- (void)respondsToPlusButton
{
    if ([self.delegate respondsToSelector:@selector(tabBarDidClickPlusButton:)]) {
        [self.myDelegate tabBarDidClickPlusButton:self];
    }
}

# pragma mark - 添加按鈕
- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        [self addSubview:self.plusButton];
    }
    return self;
}

# pragma mark - 重新布局
- (void)layoutSubviews
{
    [super layoutSubviews];
    // 設置中間按鈕的位置
    self.plusButton.center = CGPointMake(CGRectGetWidth(self.frame) * 0.5, CGRectGetHeight(self.frame) * 0.1);
    
    // 設置其他的按鈕的位置
    CGFloat w = CGRectGetWidth(self.frame) / 5;
    CGFloat index = 0;
    for (UIView *childView in self.subviews) {
        Class class = NSClassFromString(@"UITabBarButton");
        if ([childView isKindOfClass:class]) {
            childView.frame = CGRectMake(w * index, CGRectGetMinY(childView.frame), w, CGRectGetHeight(childView.frame));
            
            // 增加索引 要和中間的控件隔開
            index ++;
            if (index == 2) {
                index ++;
            }
            
        }
    }
}


# pragma mark - 重寫hitTest方法以響應點擊超出tabBar的加號按鈕
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    if (!self.clipsToBounds && !self.hidden && self.alpha > 0) {
        UIView *result = [super hitTest:point withEvent:event];
        if (result) {
            return result;
        }
        else {
            for (UIView *subview in self.subviews.reverseObjectEnumerator) {
                CGPoint subPoint = [subview convertPoint:point fromView:self];
                result = [subview hitTest:subPoint withEvent:event];
                if (result) {
                    return result;
                }
            }
        }
    }
    return nil;
}


@end

Swift
CustomTabBarViewController.swift

import UIKit

class CustomTabBarViewController: UITabBarController, UITabBarControllerDelegate, CustomTabBarDelegate {
    
    var customTabBar1 = CustomTabBar()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        let customTabBar = CustomTabBar()
        // 取消tabBar的透明效果
        customTabBar.isTranslucent = false
        // 設置tabBar的代理
        customTabBar.myDelegate = self
        self.customTabBar1 = customTabBar
        self.setValue(customTabBar, forKey: "tabBar")
        
        self.setUpTabBar()
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
    }
    
    // MARK: - 控制器的信息
    func setUpTabBar() {
        
        let demo1VC  = Demo1ViewController()
        let demo2VC  = Demo2ViewController()
        let demo4VC  = Demo4ViewController()
        let demo5VC  = Demo5ViewController()
        
        creatTabbarView(viewController: demo1VC, image: "home_normal", selectImage: "home_highlight", title: "首頁", tag: 1)
        creatTabbarView(viewController: demo2VC, image: "mycity_normal", selectImage: "mycity_highlight", title: "附近", tag: 2)
        creatTabbarView(viewController: demo4VC, image: "message_normal", selectImage: "message_highlight", title: "聊天", tag: 3)
        creatTabbarView(viewController: demo5VC, image: "account_normal", selectImage: "account_highlight", title: "我的", tag: 4)
        
        self.tabBar.tintColor = UIColor(red: 255/255.0, green: 204/255.0, blue: 13/255.0, alpha: 1)
        self.tabBar.isTranslucent = false
        
        self.viewControllers = [
            UINavigationController(rootViewController: demo1VC),
            UINavigationController(rootViewController: demo2VC),
            UINavigationController(rootViewController: demo4VC),
            UINavigationController(rootViewController: demo5VC),
        ];
        
        self.delegate = self
    }
    
    // MARK: - TabBar里面的文字圖片
    func creatTabbarView(viewController:UIViewController, image:NSString, selectImage:NSString, title:NSString, tag:NSInteger) {
        // alwaysOriginal 始終繪制圖片原始狀態,不使用Tint Color。
        viewController.tabBarItem.image = UIImage(named: image as String)?.withRenderingMode(.alwaysOriginal)
        viewController.tabBarItem.selectedImage = UIImage(named: selectImage as String)?.withRenderingMode(.alwaysOriginal)
        viewController.title = title as String
        viewController.tabBarItem.tag = tag
    }
    
    // MARK: - UITabBarControllerDelegate
    func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {

        self.customTabBar1.plusButton.isSelected = false

        return true
    }
    
    // MARK: -- CustomTabBarDelegate
    func tabBarDidClickPlusButton() {
        /**
         definesPresentationContext這一屬性決定了那個父控制器的View,
         將會以優先于UIModalPresentationCurrentContext這種呈現方式來展現自己的View。
         如果沒有父控制器設置這一屬性,那么展示的控制器將會是根視圖控制器

         modalPresentationStyle可以設置模態是否隱藏

         */
        self.customTabBar1.plusButton.isSelected = true
        
        let vc = SimpleCustomDemoViewController()
        self.definesPresentationContext = true
        vc.view.backgroundColor = UIColor.clear
        vc.modalPresentationStyle = .custom
        self.present(vc, animated: true, completion: nil)
    }
    
}

CustomTabBar.swift

import UIKit

// 聲明一個協議clcikDelegate,需要繼承NSObjectProtocol
protocol CustomTabBarDelegate: NSObjectProtocol {
    func tabBarDidClickPlusButton()
}

class CustomTabBar: UITabBar {
    // 聲明代理
    weak var myDelegate: CustomTabBarDelegate?
    
    // 懶加載中間的按鈕
    lazy var plusButton: UIButton = {
        let plusButton = UIButton()
        plusButton.setImage(UIImage.init(named: "post_normal"), for: .normal)
        plusButton.setImage(UIImage.init(named: "post_normal"), for: .highlighted)
        plusButton.titleLabel?.font = UIFont.systemFont(ofSize: 11)
        plusButton.setTitle("發布", for: .normal)
        plusButton.setTitleColor(UIColor.gray, for: .normal)
//        plusButton.setTitleColor(UIColor.init(red: 255.0/255, green: 204.0/255, blue: 13.0/255, alpha: 1), for: .selected)
        
        let buttonImg: UIImage? = plusButton.image(for: .normal)
        // 暫時沒有找到計算字符串長度的方法
//        var titleWidth: CGFloat? = NSString(string: plusButton.titleLabel?.text).size(attributes: [NSFontAttributeName:UIFont.systemFont(ofSize: 18)]).width
        let titleWidth = self
        plusButton.titleEdgeInsets = UIEdgeInsets.init(top: buttonImg!.size.height, left: -buttonImg!.size.height, bottom: -15, right: 0)
        plusButton.imageEdgeInsets = UIEdgeInsets.init(top: -15, left: 0, bottom: 0, right: -20)

        
        plusButton.frame = CGRect.init(x: 0, y: 0, width: plusButton.imageView!.image!.size.width, height: plusButton.imageView!.image!.size.height + 40)
        plusButton.addTarget(self, action: #selector(CustomTabBar.respondsToPlusButton), for: .touchUpInside)
        return plusButton
    }()

    // MARK: - CustomTabBarDelegate
    @objc func respondsToPlusButton(){
        //和oc不一樣的是,Swift中如果簡單的調用代理方法, 不用判斷代理能否響應
        if myDelegate != nil{
            myDelegate?.tabBarDidClickPlusButton()
        }
    }
 
    // MARK: - 重寫父類方法必須寫
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        fatalError("init(coder:) has not been implemented")
    }
    
    // MARK: - 添加按鈕
    override init(frame: CGRect) {
        super.init(frame: frame)
        self.addSubview(self.plusButton)
    }
    
    // MARK: - 重新布局
    override func layoutSubviews() {
        super.layoutSubviews()
        // 設置中間的按鈕的位置
        let x = self.frame.width * 0.5
        let y = self.frame.height * 0.1
        self.plusButton.center = CGPoint.init(x: x, y: y)
        
        let w = self.frame.width / 5
        var index = 0
        for childView:UIView in self.subviews {
            if childView.isKind(of: NSClassFromString("UITabBarButton")!){
                
                var isIphoneX:Bool = false
                let zeroNum:CGFloat = 0
                // 判斷是否是劉海屏
                if #available(iOS 11.0, *) {
                    isIphoneX = UIApplication.shared.keyWindow!.safeAreaInsets.bottom > zeroNum
                }
                
                if isIphoneX {
                    childView.frame = CGRect.init(x: w * CGFloat(index), y: 0, width: w, height: self.frame.size.height - 34)
                }else{
                    childView.frame = CGRect.init(x: w * CGFloat(index), y: 0, width: w, height: self.frame.size.height )
                }
                

                index+=1
                if index == 2{
                    index+=1
                }

            }
        }
    }
    
    // MARK: - 重寫hitTest方法,監聽按鈕的點擊 讓凸出tabbar的部分響應點擊
    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        
        /// 判斷是否為根控制器
        if self.isHidden {
            /// tabbar隱藏 不在主頁 系統處理
            return super.hitTest(point, with: event)
            
        }else{
            /// 將單錢觸摸點轉換到按鈕上生成新的點
            let onButton = self.convert(point, to: self.plusButton)
            /// 判斷新的點是否在按鈕上
            if self.plusButton.point(inside: onButton, with: event){
                return plusButton
            }else{
                /// 不在按鈕上 系統處理
                return super.hitTest(point, with: event)
            }
        }
    }
    
}

思路二、(類似淘寶的不用跳轉其他的界面)
1、使用KVC:如果要修系統的某些屬性,但被設為readOnly,就是用KVC,即setValue:>forKey
2、創建需要顯示UITabBarController的控制器的viewControllers
3、自定義一個tabBar、使用layoutSubviews或init(frame: CGRect)、定位到自己喜歡的位置、覆蓋需要自定義的tabBar
4、利用UITabBarControllerDelegate、控制自定義tabBar顯示隱藏

OC
TaoBaoCustomTabBarViewController.h

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface TaoBaoCustomTabBarViewController : UITabBarController

@end

NS_ASSUME_NONNULL_END

TaoBaoCustomTabBarViewController.m

#import "TaoBaoCustomTabBarViewController.h"
#import "Demo1ViewController.h"
#import "Demo2ViewController.h"
#import "Demo3ViewController.h"
#import "Demo4ViewController.h"
#import "Demo5ViewController.h"
#import "SimpleCustomDemoViewController.h"
#import "TaoBaoCustomTabBar.h"

@interface TaoBaoCustomTabBarViewController ()<UITabBarControllerDelegate, TaoBaoCustomTabBarDelegate>

@property (strong, nonatomic) TaoBaoCustomTabBar *customTabBar;

@end

@implementation TaoBaoCustomTabBarViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    TaoBaoCustomTabBar *tabBar = [[TaoBaoCustomTabBar alloc] init];
    //取消tabBar的透明效果
    tabBar.translucent = NO;
    // 設置tabBar的代理
    tabBar.myDelegate = self;
    // KVC:如果要修系統的某些屬性,但被設為readOnly,就是用KVC,即setValue:forKey:。
    [self setValue:tabBar forKey:@"tabBar"];
    self.customTabBar = tabBar;
    
    [self tabBarControllerAddChildViewController];
    
}

-(void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];
    self.navigationController.navigationBarHidden = YES;
}

# pragma mark - 添加子類的數據
- (void)tabBarControllerAddChildViewController
{
    NSArray *classControllers = [NSArray array];
    classControllers = @[@"Demo1ViewController", @"Demo2ViewController",@"Demo3ViewController" ,@"Demo4ViewController", @"Demo5ViewController"];
    NSArray *titles = @[@"", @"首頁", @"附近", @"聊天", @"我的"];
    NSArray *normalImages = @[@"", @"home_normal", @"mycity_normal", @"message_normal", @"account_normal"];
    NSArray *selectImages = @[@"", @"home_highlight", @"mycity_highlight", @"message_highlight", @"account_highlight"];
    
    [self TabbarControllerAddSubViewsControllers:classControllers addTitleArray:titles addNormalImagesArray:normalImages addSelectImageArray:selectImages];
}


# pragma mark - 初始化Tabbar里面的元素
- (void)TabbarControllerAddSubViewsControllers:(NSArray *)classControllersArray addTitleArray:(NSArray *)titleArray addNormalImagesArray:(NSArray *)normalImagesArray addSelectImageArray:(NSArray *)selectImageArray
{
    NSMutableArray *conArr = [NSMutableArray array];
    
    for (int i = 0; i < classControllersArray.count; i++) {
        
        Class cts = NSClassFromString(classControllersArray[I]);
        UIViewController *vc = [[cts alloc] init];
        UINavigationController *naVC = [[UINavigationController alloc] initWithRootViewController:vc];
        [conArr addObject:naVC];
        
        UIImage *normalImage = [[UIImage imageNamed:normalImagesArray[i]] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
        UIImage *selectImage = [[UIImage imageNamed:selectImageArray[i]] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
        
        vc.tabBarItem = [[UITabBarItem alloc] initWithTitle:titleArray[i] image:normalImage selectedImage:selectImage];
        vc.tabBarItem.tag = I;

    }
    
    self.viewControllers = conArr;
    self.tabBar.tintColor = [UIColor colorWithRed:255.0/255 green:204.0/255 blue:13.0/255 alpha:1];
    self.tabBar.translucent = NO;
    
    self.delegate = self;
}

#pragma TaoBaoCustomTabBarDelegate
/**
 *  點擊了淘寶按鈕
 */
- (void)tabBarDidClickPlusButton:(TaoBaoCustomTabBar *)tabBar
{
    self.selectedIndex =0;
    self.customTabBar.plusButton.hidden = YES;
}

# pragma mark - UITabBarControllerDelegate
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController
{
    if (viewController.tabBarItem.tag == 0) {
        self.customTabBar.plusButton.selected = NO;
        self.customTabBar.plusButton.hidden = NO;
        self.viewControllers[0].tabBarItem.image = [[UIImage imageNamed:@""] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
        self.viewControllers[0].tabBarItem.title = @"";

        return YES;
    }else{
        self.customTabBar.plusButton.hidden = YES;
        self.viewControllers[0].tabBarItem.image = [[UIImage imageNamed:@"home_normal"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
        self.viewControllers[0].tabBarItem.title = @"首頁";
        return YES;
    }
}

@end

TaoBaoCustomTabBar.h

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@class TaoBaoCustomTabBar;

@protocol TaoBaoCustomTabBarDelegate <UITabBarDelegate>

@optional
// 當點擊自定義tabbar的時候
- (void)tabBarDidClickPlusButton:(TaoBaoCustomTabBar *)tabBar;

@end


@interface TaoBaoCustomTabBar : UITabBar

@property (nonatomic, strong) UIButton *plusButton;

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

@end

NS_ASSUME_NONNULL_END

TaoBaoCustomTabBar.m

#import "TaoBaoCustomTabBar.h"

@interface TaoBaoCustomTabBar ()

@end

@implementation TaoBaoCustomTabBar

# pragma mark - 賴加載
- (UIButton *)plusButton
{
    if (_plusButton == nil) {
        _plusButton = [[UIButton alloc] init];
        [_plusButton setImage:[UIImage imageNamed:@"taobao"] forState:UIControlStateNormal];
        [_plusButton setImage:[UIImage imageNamed:@"taobao"] forState:UIControlStateHighlighted];
        
        _plusButton.frame = CGRectMake(0, 0, _plusButton.imageView.image.size.width + 1, _plusButton.imageView.image.size.height + 1);
        [_plusButton addTarget:self action:@selector(respondsToPlusButton) forControlEvents:UIControlEventTouchUpInside];
    }
    return _plusButton;
}

# pragma mark - TaoBaoCustomTabBarDelegate
- (void)respondsToPlusButton
{
    if ([self.delegate respondsToSelector:@selector(tabBarDidClickPlusButton:)]) {
        [self.myDelegate tabBarDidClickPlusButton:self];
    }
}

# pragma mark - 添加按鈕
- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        [self addSubview:self.plusButton];
    }
    return self;
}

# pragma mark - 重新布局
- (void)layoutSubviews
{
    [super layoutSubviews];

    // 設置淘寶按鈕的位置
    CGFloat w = CGRectGetWidth(self.frame) / 5;
    CGFloat index = 0;
    for (UIView *childView in self.subviews) {
        Class class = NSClassFromString(@"UITabBarButton");
        if ([childView isKindOfClass:class]) {
            if (index == 0) {
                UIView *thisView = [[UIView alloc] initWithFrame:CGRectMake(w * index, CGRectGetMinY(childView.frame), w, CGRectGetHeight(childView.frame))];
                self.plusButton.center = CGPointMake(CGRectGetWidth(thisView.frame) * 0.5, CGRectGetHeight(thisView.frame) * 0.5);
            }
        }
    }
}


# pragma mark - 重寫hitTest方法以響應點擊超出tabBar的加號按鈕
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    if (!self.clipsToBounds && !self.hidden && self.alpha > 0) {
        UIView *result = [super hitTest:point withEvent:event];
        if (result) {
            return result;
        }
        else {
            for (UIView *subview in self.subviews.reverseObjectEnumerator) {
                CGPoint subPoint = [subview convertPoint:point fromView:self];
                result = [subview hitTest:subPoint withEvent:event];
                if (result) {
                    return result;
                }
            }
        }
    }
    return nil;
}


@end

Swift
TaoBaoCustomTabBarViewController.swift

import UIKit

class TaoBaoCustomTabBarViewController: UITabBarController, UITabBarControllerDelegate, TaoBaoCustomTabBarDelegate {
    
    var customTabBar1 = TaoBaoCustomTabBar()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        let customTabBar = TaoBaoCustomTabBar()
        // 取消tabBar的透明效果
        customTabBar.isTranslucent = false
        // 設置tabBar的代理
        customTabBar.myDelegate = self
        self.customTabBar1 = customTabBar
        self.setValue(customTabBar, forKey: "tabBar")
        
        self.setUpTabBar()
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
    }
    
    // MARK: - 控制器的信息
    func setUpTabBar() {
        
        let demo1VC  = Demo1ViewController()
        let demo2VC  = Demo2ViewController()
        let demo3VC  = Demo3ViewController()
        let demo4VC  = Demo4ViewController()
        let demo5VC  = Demo5ViewController()
        
        creatTabbarView(viewController: demo1VC, image: "", selectImage: "", title: "", tag: 0)
        creatTabbarView(viewController: demo2VC, image: "home_normal", selectImage: "home_highlight", title: "首頁", tag: 1)
        creatTabbarView(viewController: demo3VC, image: "mycity_normal", selectImage: "mycity_highlight", title: "附近", tag: 2)
        creatTabbarView(viewController: demo4VC, image: "message_normal", selectImage: "message_highlight", title: "聊天", tag: 3)
        creatTabbarView(viewController: demo5VC, image: "account_normal", selectImage: "account_highlight", title: "我的", tag: 4)
        
        self.tabBar.tintColor = UIColor(red: 255/255.0, green: 204/255.0, blue: 13/255.0, alpha: 1)
        self.tabBar.isTranslucent = false
        
        self.viewControllers = [
            UINavigationController(rootViewController: demo1VC),
            UINavigationController(rootViewController: demo2VC),
            UINavigationController(rootViewController: demo3VC),
            UINavigationController(rootViewController: demo4VC),
            UINavigationController(rootViewController: demo5VC),
        ];
        
        self.delegate = self
    }
    
    // MARK: - TabBar里面的文字圖片
    func creatTabbarView(viewController:UIViewController, image:NSString, selectImage:NSString, title:NSString, tag:NSInteger) {
        // alwaysOriginal 始終繪制圖片原始狀態,不使用Tint Color。
        viewController.tabBarItem.image = UIImage(named: image as String)?.withRenderingMode(.alwaysOriginal)
        viewController.tabBarItem.selectedImage = UIImage(named: selectImage as String)?.withRenderingMode(.alwaysOriginal)
        viewController.tabBarItem.title = title as String
        viewController.tabBarItem.tag = tag
    }
    
    // MARK: - UITabBarControllerDelegate
    func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {

        if viewController.tabBarItem.tag != 0{
            self.customTabBar1.plusButton.isSelected = false
            self.customTabBar1.plusButton.isHidden = true
            self.viewControllers?[0].tabBarItem.image = UIImage.init(named: "home_normal")?.withRenderingMode(.alwaysOriginal)
            self.viewControllers?[0].tabBarItem.title = "首頁"
        }

        return true
    }
    
    // MARK: -- TaoBaoCustomTabBarDelegate
    func tabBarDidClickPlusButton(tabBar:TaoBaoCustomTabBar) {
        self.selectedIndex = 0;
        tabBar.plusButton.isSelected = false;
        tabBar.plusButton.isHidden = false;
        self.viewControllers?[0].tabBarItem.image = UIImage.init(named: "")?.withRenderingMode(.alwaysOriginal)
        self.viewControllers?[0].tabBarItem.title = ""
    }
    
}


TaoBaoCustomTabBar.swift

import UIKit

// 聲明一個協議clcikDelegate,需要繼承NSObjectProtocol
protocol TaoBaoCustomTabBarDelegate: NSObjectProtocol {
    func tabBarDidClickPlusButton(tabBar:TaoBaoCustomTabBar)
}

class TaoBaoCustomTabBar: UITabBar {
    // 聲明代理
    weak var myDelegate: TaoBaoCustomTabBarDelegate?
    
    // 懶加載中間的按鈕
    lazy var plusButton: UIButton = {
        let plusButton = UIButton()
        plusButton.setImage(UIImage.init(named: "taobao"), for: .normal)
        plusButton.setImage(UIImage.init(named: "taobao"), for: .highlighted)
        plusButton.titleLabel?.font = UIFont.systemFont(ofSize: 11)
        plusButton.setTitle("", for: .normal)

        plusButton.frame = CGRect.init(x: 0, y: 0, width: plusButton.imageView!.image!.size.width, height: plusButton.imageView!.image!.size.height + 40)
        plusButton.addTarget(self, action: #selector(TaoBaoCustomTabBar.respondsToPlusButton), for: .touchUpInside)
        return plusButton
    }()

    // MARK: - TaoBaoCustomTabBarDelegate
    @objc func respondsToPlusButton(){
        //和oc不一樣的是,Swift中如果簡單的調用代理方法, 不用判斷代理能否響應
        if myDelegate != nil{
            myDelegate?.tabBarDidClickPlusButton(tabBar: self)
        }
    }
 
    // MARK: - 重寫父類方法必須寫
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        fatalError("init(coder:) has not been implemented")
    }
    
    // MARK: - 添加按鈕
    override init(frame: CGRect) {
        super.init(frame: frame)
        self.addSubview(self.plusButton)
    }
    
    // MARK: - 重新布局
    override func layoutSubviews() {
        super.layoutSubviews()
        
        // 設置淘寶按鈕的位置
        let w = self.frame.width / 5
        let index = 0
        for childView:UIView in self.subviews {
            if childView.isKind(of: NSClassFromString("UITabBarButton")!){

                if index == 0 {
                    var isIphoneX:Bool = false
                    let zeroNum:CGFloat = 0
                    // 判斷是否是劉海屏
                    if #available(iOS 11.0, *) {
                        isIphoneX = UIApplication.shared.keyWindow!.safeAreaInsets.bottom > zeroNum
                    }
                    
                    if isIphoneX {
                        self.plusButton.frame = CGRect.init(x: w * CGFloat(index), y: 0, width: w, height: self.frame.size.height - 34)
                    }else{
                        self.plusButton.frame = CGRect.init(x: w * CGFloat(index), y: 0, width: w, height: self.frame.size.height )
                    }
                }

            }
        }
    }
    
    // MARK: - 重寫hitTest方法,監聽按鈕的點擊 讓凸出tabbar的部分響應點擊
    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        
        /// 判斷是否為根控制器
        if self.isHidden {
            /// tabbar隱藏 不在主頁 系統處理
            return super.hitTest(point, with: event)
            
        }else{
            /// 將單錢觸摸點轉換到按鈕上生成新的點
            let onButton = self.convert(point, to: self.plusButton)
            /// 判斷新的點是否在按鈕上
            if self.plusButton.point(inside: onButton, with: event){
                return plusButton
            }else{
                /// 不在按鈕上 系統處理
                return super.hitTest(point, with: event)
            }
        }
    }
    
}

思路三(動畫音效按鈕tabbar)
tabbar點擊的時候會調用didSelectItem方法
讀取父控件對應的tabbar、對tabbar實現幀動畫
點擊對聲音使用AudioToolbox框架

OC
AnimationTabBarViewController.h

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface AnimationTabBarViewController : UITabBarController

@end

NS_ASSUME_NONNULL_END

AnimationTabBarViewController.m

#import "AnimationTabBarViewController.h"
#import "Demo1ViewController.h"
#import "Demo2ViewController.h"
#import "Demo3ViewController.h"
#import "Demo4ViewController.h"
#import "Demo5ViewController.h"
// 音效框架
#import <AudioToolbox/AudioToolbox.h>

@interface AnimationTabBarViewController ()<UITabBarControllerDelegate>

@end

@implementation AnimationTabBarViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self tabBarControllerAddChildViewController];
    
}

-(void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];
    self.navigationController.navigationBarHidden = YES;
}

# pragma mark - 添加子類的數據
- (void)tabBarControllerAddChildViewController
{
    NSArray *classControllers = [NSArray array];
    classControllers = @[@"Demo1ViewController", @"Demo2ViewController", @"Demo3ViewController", @"Demo4ViewController", @"Demo5ViewController"];
    NSArray *titles = @[@"首頁", @"附近", @"發布", @"聊天", @"我的"];
    NSArray *normalImages = @[@"home_normal", @"mycity_normal", @"mycity_normal", @"message_normal", @"account_normal"];
    NSArray *selectImages = @[@"home_highlight", @"mycity_highlight", @"mycity_highlight", @"message_highlight", @"account_highlight"];
    
    [self TabbarControllerAddSubViewsControllers:classControllers addTitleArray:titles addNormalImagesArray:normalImages addSelectImageArray:selectImages];
}


# pragma mark - 初始化Tabbar里面的元素
- (void)TabbarControllerAddSubViewsControllers:(NSArray *)classControllersArray addTitleArray:(NSArray *)titleArray addNormalImagesArray:(NSArray *)normalImagesArray addSelectImageArray:(NSArray *)selectImageArray
{
    NSMutableArray *conArr = [NSMutableArray array];
    
    for (int i = 0; i < classControllersArray.count; i++) {
        
        Class cts = NSClassFromString(classControllersArray[I]);
        UIViewController *vc = [[cts alloc] init];
        UINavigationController *naVC = [[UINavigationController alloc] initWithRootViewController:vc];
        [conArr addObject:naVC];
        
        UIImage *normalImage = [[UIImage imageNamed:normalImagesArray[i]] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
        UIImage *selectImage = [[UIImage imageNamed:selectImageArray[i]] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
        vc.tabBarItem = [[UITabBarItem alloc] initWithTitle:titleArray[i] image:normalImage selectedImage:selectImage];
        vc.tabBarItem.tag = I;
        
    }
    
    self.viewControllers = conArr;
    self.tabBar.tintColor = [UIColor colorWithRed:255.0/255 green:204.0/255 blue:13.0/255 alpha:1];
    self.tabBar.translucent = NO;
    self.delegate = self;
}

# pragma mark - UITabBarControllerDelegate
/**
 點擊TabBar的時候調用
 */
- (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item
{
    [self animationWithIndex:item.tag];
}

- (void)animationWithIndex:(NSInteger) index {
    // 得到當前tabbar的下標
    NSMutableArray * tabbarbuttonArray = [NSMutableArray array];
    for (UIView *tabBarButton in self.tabBar.subviews) {
        if ([tabBarButton isKindOfClass:NSClassFromString(@"UITabBarButton")]) {
            [tabbarbuttonArray addObject:tabBarButton];
        }
    }
    /**
     對當前下標的tabbar使用幀動畫
     可以根據UI的具體要求進行動畫渲染
     */
    CABasicAnimation*pulse = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
    pulse.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    pulse.duration = 0.2;
    pulse.repeatCount = 1;
    pulse.autoreverses = YES;
    pulse.fromValue = [NSNumber numberWithFloat:0.7];
    pulse.toValue = [NSNumber numberWithFloat:1.3];
    [[tabbarbuttonArray[index] layer] addAnimation:pulse forKey:nil];
    [self playSoundEffect:@"music" type:@"wav"];
}

# pragma mark - 播放音效的方法
- (void)playSoundEffect:(NSString *)name type:(NSString *)type{
    // 獲取音效文件路徑
    NSString *resoucePath = [[NSBundle mainBundle] pathForResource:name ofType:type];
    SystemSoundID soundID;
    // 地址轉換和賦值
    AudioServicesCreateSystemSoundID((__bridge CFURLRef)[NSURL fileURLWithPath:resoucePath], &soundID);
    // 開始播放音效
    AudioServicesPlaySystemSound(soundID);
}

@end

AnimationTabBarViewController.swift

import UIKit
// 音效框架
import AudioToolbox

class AnimationTabBarViewController: UITabBarController, UITabBarControllerDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()
        self.setUpTabBar()
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
    }
    
    // MARK: - 控制器的信息
    func setUpTabBar() {
        
        let demo1VC  = Demo1ViewController()
        let demo2VC  = Demo2ViewController()
        let demo3VC  = Demo3ViewController()
        let demo4VC  = Demo4ViewController()
        let demo5VC  = Demo5ViewController()
        
        creatTabbarView(viewController: demo1VC, image: "home_normal", selectImage: "home_highlight", title: "首頁", tag: 0)
        creatTabbarView(viewController: demo2VC, image: "mycity_normal", selectImage: "mycity_highlight", title: "附近", tag: 1)
        creatTabbarView(viewController: demo3VC, image: "mycity_normal", selectImage: "mycity_highlight", title: "發布", tag: 2)
        creatTabbarView(viewController: demo4VC, image: "message_normal", selectImage: "message_highlight", title: "聊天", tag: 3)
        creatTabbarView(viewController: demo5VC, image: "account_normal", selectImage: "account_highlight", title: "我的", tag: 4)
        
        self.viewControllers = [
            UINavigationController(rootViewController: demo1VC),
            UINavigationController(rootViewController: demo2VC),
            UINavigationController(rootViewController: demo3VC),
            UINavigationController(rootViewController: demo4VC),
            UINavigationController(rootViewController: demo5VC),
        ];
        
        self.tabBar.tintColor = UIColor(red: 255/255.0, green: 204/255.0, blue: 13/255.0, alpha: 1)
        self.tabBar.isTranslucent = false
        self.delegate = self
    }
    
    // MARK: - TabBar里面的文字圖片
    func creatTabbarView(viewController:UIViewController, image:NSString, selectImage:NSString, title:NSString, tag:NSInteger) {
        // alwaysOriginal 始終繪制圖片原始狀態,不使用Tint Color。
        viewController.tabBarItem.image = UIImage(named: image as String)?.withRenderingMode(.alwaysOriginal)
        viewController.tabBarItem.selectedImage = UIImage(named: selectImage as String)?.withRenderingMode(.alwaysOriginal)
        viewController.title = title as String
        viewController.tabBarItem.tag = tag
    }
    
    // MARK: - UITabBarControllerDelegate
    /**
     點擊TabBar的時候調用
     */
    override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
        self.touchAnimation(index: item.tag)
    }
    
    func touchAnimation(index:NSInteger){
        // 得到當前tabbar的下標
        var tabbarbuttonArray:NSMutableArray!
        tabbarbuttonArray = NSMutableArray.init()
        for tabBarButton:UIView in self.tabBar.subviews {
            if tabBarButton.isKind(of: NSClassFromString("UITabBarButton")!){
                tabbarbuttonArray.add(tabBarButton)
            }
        }
        /**
         對當前下標的tabbar使用幀動畫
         可以根據UI的具體要求進行動畫渲染
         */
        let pulse = CABasicAnimation.init(keyPath: "transform.scale")
        pulse.timingFunction = CAMediaTimingFunction.init(name: .easeInEaseOut)
        pulse.duration = 0.2
        pulse.repeatCount = 1
        pulse.autoreverses = true
        pulse.fromValue = 0.7
        pulse.toValue = 1.3
        let thisView = tabbarbuttonArray[index] as! UIView
        thisView.layer.add(pulse, forKey: nil)
        
        self.playSoundEffect(name: "music", type: "wav")
    }
    
    // MARK: - 播放音效的方法
    func playSoundEffect(name:String, type:String) {
        //獲取聲音地址
        let resoucePath = Bundle.main.path(forResource: name, ofType: type)
        var soundID:SystemSoundID = 0
        //地址轉換
        let baseURL = NSURL(fileURLWithPath: resoucePath!)
        //賦值
        AudioServicesCreateSystemSoundID(baseURL, &soundID)
        //播放聲音
        AudioServicesPlaySystemSound(soundID)
        
    }
}

思路四(京東tabbar)
1、在app文件里設置window的背景色、根據需求設置
2、寫一個父類、讓子控制器繼承他。這個父類控制tabbar的動畫
3、設置KVO模式、監聽判斷tabbar是否需要動畫

OC代碼
AppDelegate.m

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    self.window.backgroundColor = [UIColor whiteColor];
    return YES;
}

JDAnimationTabBarViewController.h

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface JDAnimationTabBarViewController : UITabBarController

@end

NS_ASSUME_NONNULL_END

JDAnimationTabBarViewController.m

#import "JDAnimationTabBarViewController.h"
#import "Demo7ViewController.h"
#import "Demo2ViewController.h"
#import "Demo3ViewController.h"
#import "Demo4ViewController.h"
#import "Demo5ViewController.h"

@interface JDAnimationTabBarViewController ()

@end

@implementation JDAnimationTabBarViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    [self tabBarControllerAddChildViewController];
    
}

-(void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];
    self.navigationController.navigationBarHidden = YES;
}

# pragma mark - 添加子類的數據
- (void)tabBarControllerAddChildViewController
{
    NSArray *classControllers = [NSArray array];
    classControllers = @[@"Demo7ViewController", @"Demo2ViewController", @"Demo3ViewController", @"Demo4ViewController", @"Demo5ViewController"];
    NSArray *titles = @[@"首頁", @"附近", @"是的", @"聊天", @"我的"];
    NSArray *normalImages = @[@"home_normal", @"mycity_normal", @"mycity_normal", @"message_normal", @"account_normal"];
    NSArray *selectImages = @[@"home_highlight", @"mycity_highlight", @"mycity_highlight", @"message_highlight", @"account_highlight"];
    
    [self TabbarControllerAddSubViewsControllers:classControllers addTitleArray:titles addNormalImagesArray:normalImages addSelectImageArray:selectImages];
}


# pragma mark - 初始化Tabbar里面的元素
- (void)TabbarControllerAddSubViewsControllers:(NSArray *)classControllersArray addTitleArray:(NSArray *)titleArray addNormalImagesArray:(NSArray *)normalImagesArray addSelectImageArray:(NSArray *)selectImageArray
{
    NSMutableArray *conArr = [NSMutableArray array];
    
    for (int i = 0; i < classControllersArray.count; i++) {
        
        Class cts = NSClassFromString(classControllersArray[I]);
        UIViewController *vc = [[cts alloc] init];
        UINavigationController *naVC = [[UINavigationController alloc] initWithRootViewController:vc];
        [conArr addObject:naVC];
        
        UIImage *normalImage = [[UIImage imageNamed:normalImagesArray[i]] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
        UIImage *selectImage = [[UIImage imageNamed:selectImageArray[i]] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
        
        vc.tabBarItem = [[UITabBarItem alloc] initWithTitle:titleArray[i] image:normalImage selectedImage:selectImage];
        vc.tabBarItem.tag = I;
    }
    
    self.viewControllers = conArr;
    self.tabBar.tintColor = [UIColor colorWithRed:255.0/255 green:204.0/255 blue:13.0/255 alpha:1];
    self.tabBar.translucent = NO;
}

@end

父類控制器讓tabbar的控制器繼承他
SuperViewController.h

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface SuperViewController : UIViewController

@end

NS_ASSUME_NONNULL_END

SuperViewController.m

#import "SuperViewController.h"


@interface SuperViewController ()

@end

@implementation SuperViewController

- (void)viewDidLoad {
    [super viewDidLoad];
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    //如果KVO、觀察者有改變
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(isAnimation:) name:@"isAnimation" object:nil];
}

// 得到監聽值
- (void)isAnimation:(NSNotification *)notification{
    NSNumber *number = [notification object];
    int num = [number intValue];
    if (num == 0) {
        self.tabBarController.tabBar.frame = CGRectMake(self.tabBarController.tabBar.frame.origin.x, self.tabBarController.tabBar.frame.origin.y + self.tabBarController.tabBar.frame.size.height, self.tabBarController.tabBar.frame.size.width, self.tabBarController.tabBar.frame.size.height);
    }else{
        [UIView animateWithDuration:0.5 animations:^{
            self.tabBarController.tabBar.frame = CGRectMake(self.tabBarController.tabBar.frame.origin.x, self.tabBarController.tabBar.frame.origin.y - self.tabBarController.tabBar.frame.size.height, self.tabBarController.tabBar.frame.size.width, self.tabBarController.tabBar.frame.size.height);
        }];
    }
}
@end

跳轉的界面
Demo6ViewController.h

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface Demo6ViewController : UIViewController

@end

NS_ASSUME_NONNULL_END

Demo6ViewController.m

#import "Demo6ViewController.h"

@interface Demo6ViewController ()

@end

@implementation Demo6ViewController

//移除KVO、觀察者
- (void)dealloc {
    [self removeObserver:self forKeyPath:@"isAnimation" context:nil];
}

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // Do any additional setup after loading the view.
    self.view.backgroundColor = [UIColor yellowColor];
    
    // 設置KVO、觀察者
    [self addObserver:self forKeyPath:@"isAnimation" options:NSKeyValueObservingOptionNew context:nil];
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    // 對KVO、觀察者發送信息
    [[NSNotificationCenter defaultCenter] postNotificationName:@"isAnimation" object:@0];
}

- (void)viewDidDisappear:(BOOL)animated{
    [super viewDidDisappear:animated];
    // 對KVO、觀察者發送信息
    [[NSNotificationCenter defaultCenter] postNotificationName:@"isAnimation" object:@1];
}

@end

tabbar控制器
Demo7ViewController.h

#import <UIKit/UIKit.h>
#import "SuperViewController.h"

NS_ASSUME_NONNULL_BEGIN

@interface Demo7ViewController : SuperViewController

@end

NS_ASSUME_NONNULL_END

Demo7ViewController.m

#import "Demo7ViewController.h"
#import "Demo6ViewController.h"

@interface Demo7ViewController ()

@end

@implementation Demo7ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor redColor];
    
    UIButton *backBtn = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
    [backBtn setTitle:@"Back" forState:UIControlStateNormal];
    [backBtn addTarget:self action:@selector(backBtn) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:backBtn];
    
    UIButton *pushBtn = [[UIButton alloc] initWithFrame:CGRectMake(0, 200, 200, 200)];
    [pushBtn setTitle:@"push" forState:UIControlStateNormal];
    [pushBtn addTarget:self action:@selector(pushBtn) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:pushBtn];
}

# pragma mark - 返回按鈕
- (void)backBtn
{
    [self.tabBarController dismissViewControllerAnimated:YES completion:nil];
}

# pragma mark - push
- (void)pushBtn
{
    Demo6ViewController *vc = [[Demo6ViewController alloc] init];
    vc.hidesBottomBarWhenPushed = YES;
    [self.navigationController pushViewController:vc animated:YES];
}

@end

Swfit代碼
app

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        self.window?.backgroundColor = UIColor.white
        return true
    }

JDAnimationTabBarViewController

import UIKit

class JDAnimationTabBarViewController: UITabBarController {

    override func viewDidLoad() {
        super.viewDidLoad()
        self.setUpTabBar()
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
    }
    
    // MARK: - 控制器的信息
    func setUpTabBar() {
        
        let demo1VC  = Demo7ViewController()
        let demo2VC  = Demo2ViewController()
        let demo3VC  = Demo3ViewController()
        let demo4VC  = Demo4ViewController()
        let demo5VC  = Demo5ViewController()
        
        creatTabbarView(viewController: demo1VC, image: "home_normal", selectImage: "home_highlight", title: "首頁", tag: 1)
        creatTabbarView(viewController: demo2VC, image: "mycity_normal", selectImage: "mycity_highlight", title: "附近", tag: 2)
        creatTabbarView(viewController: demo3VC, image: "mycity_normal", selectImage: "mycity_highlight", title: "你好", tag: 3)
        creatTabbarView(viewController: demo4VC, image: "message_normal", selectImage: "message_highlight", title: "聊天", tag: 4)
        creatTabbarView(viewController: demo5VC, image: "account_normal", selectImage: "account_highlight", title: "我的", tag: 5)
        
        self.tabBar.tintColor = UIColor(red: 255/255.0, green: 204/255.0, blue: 13/255.0, alpha: 1)
        self.tabBar.isTranslucent = false
        
        self.viewControllers = [
            UINavigationController(rootViewController: demo1VC),
            UINavigationController(rootViewController: demo2VC),
            UINavigationController(rootViewController: demo3VC),
            UINavigationController(rootViewController: demo4VC),
            UINavigationController(rootViewController: demo5VC),
        ];
        
    }
    
    // MARK: - TabBar里面的文字圖片
    func creatTabbarView(viewController:UIViewController, image:NSString, selectImage:NSString, title:NSString, tag:NSInteger) {
        // alwaysOriginal 始終繪制圖片原始狀態,不使用Tint Color。
        viewController.tabBarItem.image = UIImage(named: image as String)?.withRenderingMode(.alwaysOriginal)
        viewController.tabBarItem.selectedImage = UIImage(named: selectImage as String)?.withRenderingMode(.alwaysOriginal)
        viewController.title = title as String
        viewController.tabBarItem.tag = tag
        
    }
    

}

父類控制器
SuperViewController

import UIKit

class SuperViewController: UIViewController {
    
    var index:Int = 0
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        //如果KVO、觀察者有改變
        NotificationCenter.default.addObserver(self, selector: #selector(isAnimation), name: NSNotification.Name.init(rawValue: "isAnimation"), object: nil)
        
        if self.index == 1 {
            self.tabBarController?.tabBar.frame = CGRect.init(x: self.tabBarController!.tabBar.frame.origin.x, y: self.tabBarController!.tabBar.frame.origin.y + self.tabBarController!.tabBar.frame.size.height, width: self.tabBarController!.tabBar.frame.size.width, height: self.tabBarController!.tabBar.frame.size.height)
        }
        
    }
    
    // 得到監聽值
    @objc func isAnimation(notification: Notification) {
        let number: NSNumber = notification.object as! NSNumber
        let num: Int = number.intValue
        
        if num == 0{
            self.index = 1
        }else{
            self.index = 0
            UIView.animate(withDuration: 0.5) {
                self.tabBarController?.tabBar.frame = CGRect.init(x: self.tabBarController!.tabBar.frame.origin.x, y: self.tabBarController!.tabBar.frame.origin.y - self.tabBarController!.tabBar.frame.size.height, width: self.tabBarController!.tabBar.frame.size.width, height: self.tabBarController!.tabBar.frame.size.height)
            }
        }
    }
}

跳轉控制器
Demo6ViewController

import UIKit

class Demo6ViewController: UIViewController {
    
    // MARK: - 類似OC dealloc
    deinit {
        self.removeObserver(self, forKeyPath: "isAnimation", context: nil)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.backgroundColor = UIColor.yellow
        // 設置KVO、觀察者
        self.addObserver(self, forKeyPath: "isAnimation", options: .new, context: nil)
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        let number:NSNumber = 0

        // 對KVO、觀察者發送信息
//        NotificationCenter.default.post(name: NSNotification.Name.init(rawValue: "isAnimation"), object: number)
        NotificationCenter.default.post(name: NSNotification.Name.init(rawValue: "isAnimation"), object: number)
    }
    
    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        let number:NSNumber = 1
        // 對KVO、觀察者發送信息
        NotificationCenter.default.post(name: NSNotification.Name.init(rawValue: "isAnimation"), object: number)
    }
}

tabbar控制器
Demo7ViewController

import UIKit

class Demo7ViewController: SuperViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.backgroundColor = UIColor.red
        
        let backBtn = UIButton(frame: CGRect(x: 100, y: 100, width: 100, height: 100))
        backBtn.setTitle("back", for: .normal)
        // 這里的#selector 不要重名
        backBtn.addTarget(self, action: #selector(backBtnCkick), for: .touchUpInside)
        self.view.addSubview(backBtn)
        
        let pushBtn = UIButton(frame: CGRect(x: 100, y: 200, width: 100, height: 100))
        pushBtn.setTitle("push", for: .normal)
        // 這里的#selector 不要重名
        pushBtn.addTarget(self, action: #selector(pushBtnCkick), for: .touchUpInside)
        self.view.addSubview(pushBtn)
    }
    
    // MARK: - 返回按鈕
    @objc func backBtnCkick(){
        self.tabBarController?.dismiss(animated: true, completion: nil)
    }
    
    // MARK: - push按鈕
    @objc func pushBtnCkick(){
        let demo6VC = Demo6ViewController()
        demo6VC.hidesBottomBarWhenPushed = true
        self.navigationController?.pushViewController(demo6VC, animated: true)
    }


}

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 簡介 UITabBar是iOS App中經常使用的系統控件,比如知名App:新浪微博,微信,騰訊QQ等。在實際的項...
    清蘂翅膀的技術閱讀 1,885評論 0 6
  • Swift1> Swift和OC的區別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴謹 對...
    cosWriter閱讀 11,135評論 1 32
  • 漸變的面目拼圖要我怎么拼? 我是疲乏了還是投降了? 不是不允許自己墜落, 我沒有滴水不進的保護膜。 就是害怕變得面...
    悶熱當乘涼閱讀 4,304評論 0 13
  • ?楔子Runtime是什么?見名知意,其概念無非就是“因為 Objective-C 是一門動態語言,所以它需要一個...
    abb266389fd0閱讀 11,412評論 37 310
  • 周末是難得休息的日子 有點時間可以自由安排 我選擇休息 健身 倘若有時間再去閱讀一下 身體需要鍛煉 這個是重中之重...
    三三不惑閱讀 237評論 0 5