美文网首页奔跑吧 iOSiOS开发iOS Developer
iOS开发之自定义TabBarController-prese

iOS开发之自定义TabBarController-prese

作者: zhifenx | 来源:发表于2016-09-22 22:15 被阅读2288次
    点击TabBar present出控制器.gif

    �如上图这种点击TabBar中间Button时present(模态)出控制器,而点击TabBar其它的Button则是苹果默认的直接切换视图的方式,现在很多APP都在使用,特别是直播APP,基本都把直播端模块放在这,最近在仿喵播时正好做到这,�就想在网上找现成的框架,结果一直没找到能满足这种需求的框架,就自己动手写了一个,没有仔细打磨算不上框架,但绝对简单好用!

    自定义TabBarController实现原理很简单,无非是用自定义的Button替换掉苹果自带的TabBar上的Button,一般目的是想TabBar上方显示按钮图片,下面是文字;也就是每个Button下面有一个Label。实现这些的重点是计算ButtonLabel的宽度和X坐标值。

    下面是JFTabBarController代码实现:

    1、 新建三个类:

    • JFTabBar继承自UIview
    • JFTabBarButton继承自UIButton
    • JFTabBarController继承自UITabBarController

    2、具体代码:

    • JFTabBar.h
    #import <UIKit/UIKit.h>
    
    @class JFTabBar;
    
    @protocol JFTabBarDelegate <NSObject>
    
    @optional
    
    - (void)tabBar:(JFTabBar *)tabBar didSelectedButtonFrom:(int)from to:(int)to;
    
    @end
    
    @interface JFTabBar : UIView
    
    - (void)addTabBarButtonWithItem:(UITabBarItem *)item;
    
    - (void)customTheMiddleButtonWithImageName:(NSString *)imageName;
    
    @property (nonatomic, weak) id<JFTabBarDelegate> delegate;
    
    @end
    
    • JFTabBar.m
    #import "JFTabBar.h"
    
    #import "JFTabBarButton.h"
    
    //中间按钮被点击的通知
    //此通知需要在JFTabBarController中监听
    static NSString * const JFTabBarClickMiddleButtonDidNotification = @"JFTabBarClickMiddleButtonDidNotification";
    
    @interface JFTabBar(){
        CGFloat _buttonW;
    }
    
    @property (nonatomic, weak) JFTabBarButton *selectedButton;
    
    @property (nonatomic, strong) UIButton *middleButton;
    
    @end
    
    @implementation JFTabBar
    
    - (void)addTabBarButtonWithItem:(UITabBarItem *)item {
        JFTabBarButton *button = [[JFTabBarButton alloc] init];
        [self addSubview:button];
        button.item = item;
        [button addTarget:self action:@selector(buttonClick:) forControlEvents:UIControlEventTouchDown];
        if (self.subviews.count == 1) {
            [self buttonClick:button];
        }
    }
    
    - (void)buttonClick:(JFTabBarButton *)button {
        if ([self.delegate respondsToSelector:@selector(tabBar:didSelectedButtonFrom:to:)]) {
            [self.delegate tabBar:self didSelectedButtonFrom:(int)self.selectedButton.tag to:(int)button.tag];
        }
        self.selectedButton.selected = NO;
        button.selected = YES;
        self.selectedButton = button;
    }
    
    /**
     *  self.subviews.count + 1 这里加1是将button的width按三个button计算,实际上是两个button(如果不想present就不需要加1,下面两个if判断也可以去掉)
     *  两个if判断:1、是将button的x坐标按三个button计算;2、tag值回归正常,不然无法正常切换控制器
     *  如你需要添加更多的控制器,这里就需要你自己计算,然后修改以上两点
     */
    - (void)layoutSubviews {
        [super layoutSubviews];
        CGFloat buttonH = self.frame.size.height;
        _buttonW = self.frame.size.width / (self.subviews.count + 1);
        CGFloat buttonY = 0;
        for (int index = 0; index < self.subviews.count; index++) {
            JFTabBarButton *button = self.subviews[index];
            if (index == 1) index ++;
            CGFloat buttonX = index * _buttonW;
            button.frame = CGRectMake(buttonX, buttonY, _buttonW, buttonH);
            if (index == 2) index --;
            button.tag = index;
        }
        [self customTheMiddleButtonWithImageName:@"toolbar_live"];
    }
    
    //自定义中间button按钮
    - (void)customTheMiddleButtonWithImageName:(NSString *)imageName {
    //  将Button居中
        CGFloat middleButtonX = self.center.x - _buttonW / 2;
        _middleButton = [[UIButton alloc] initWithFrame:CGRectMake(middleButtonX, 0, _buttonW, self.frame.size.height)];
        [_middleButton setImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal];
        [_middleButton addTarget:self action:@selector(didClickedMiddleButton:) forControlEvents:UIControlEventTouchDown];
        [self addSubview:_middleButton];
    }
    
    - (void)didClickedMiddleButton:(UIButton *)sender {
        //注册中间button被点击通知
        [[NSNotificationCenter defaultCenter] postNotificationName:JFTabBarClickMiddleButtonDidNotification object:self];
    }
    @end
    
    • JFTabBarButton.h
    #import <UIKit/UIKit.h>
    
    @interface JFTabBarButton : UIButton
    
    @property (nonatomic, strong) UITabBarItem *item;
    
    @end
    
    • JFTabBarButton.m
    static const double JFTabBarButtonImageRatio = 0.8;
    #import "JFTabBarButton.h"
    
    @implementation JFTabBarButton
    
    - (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:[UIColor grayColor] forState:UIControlStateNormal];
        }
        return self;
    }
    
    - (void)setHighlighted:(BOOL)highlighted {}
    
    - (CGRect)imageRectForContentRect:(CGRect)contentRect{
        CGFloat imageW = contentRect.size.width;
        CGFloat imageH = contentRect.size.height * JFTabBarButtonImageRatio;
        return CGRectMake(0, 10, imageW, imageH);
    }
    
    //Button下需要文字时打开
    //- (CGRect)titleRectForContentRect:(CGRect)contentRect {
    //    CGFloat titleY = contentRect.size.height * JFTabBarButtonImageRatio;
    //    CGFloat titleW = contentRect.size.width;
    //    CGFloat titleH = contentRect.size.height - titleY;
    //    return CGRectMake(0, titleY, titleW, titleH);
    //}
    
    - (void)setItem:(UITabBarItem *)item {
        _item = item;
        //Button下需要文字时打开
    //    [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 {
        //Button下需要文字时打开
    //    [self.item removeObserver:self forKeyPath:@"title"];
        [self.item removeObserver:self forKeyPath:@"image"];
        [self.item removeObserver:self forKeyPath:@"selectedImage"];
    }
    
    - (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];
    }
    
    @end
    
    • JFTabBarController.h

    - (void)addAllChildViewControllers中添加除中间那个你需要present(模态)出的控制器

    #import <UIKit/UIKit.h>
    
    extern NSString * const JFTabBarClickMiddleButtonDidNotification;
    
    @interface JFTabBarController : UITabBarController
    
    @end
    
    • JFTabBarController.m
    #import "JFTabBarController.h"
    
    #import "JFTabBar.h"
    #import "JFDisplayViewController.h"
    #import "JFMeViewController.h"
    #import "JFLiveViewController.h"
    
    @interface JFTabBarController ()<JFTabBarDelegate>
    
    @property (nonatomic, weak) JFTabBar *customTabBar;
    
    @end
    
    @implementation JFTabBarController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        [self customTabBarUI];
    //  添加子控制器
        [self addAllChildViewControllers];
    
    //  监听中间按钮点击事件
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(presentLiveController) name:@"JFTabBarClickMiddleButtonDidNotification" object:nil];
    }
    //  移除原生的TabBar
    - (void)viewWillAppear:(BOOL)animated {
        [super viewWillAppear:animated];
        for (UIView *childView in self.tabBar.subviews) {
            if ([childView isKindOfClass:[UIControl class]]) {
                [childView removeFromSuperview];
            }
        }
    }
    
    - (void)customTabBarUI {
        JFTabBar *customTabBar = [[JFTabBar alloc] init];
        customTabBar.frame = self.tabBar.bounds;
        customTabBar.delegate = self;
        [self.tabBar addSubview:customTabBar];
        self.customTabBar = customTabBar;
    }
    
    - (void)tabBar:(JFTabBar *)tabBar didSelectedButtonFrom:(int)from to:(int)to{
        self.selectedIndex = to;
    }
    
    //   下面换成你自己需要添加的控制器就好,只添加除中间需要present(模态)出的控制器。
    - (void)addAllChildViewControllers {
        JFDisplayViewController *displayVC = [[JFDisplayViewController alloc] init];
        [self addChildViewController:displayVC title:@"视频" imageName:@"toolbar_home" selectedImageName:@"toolbar_home_sel"];
        JFMeViewController *meVC = [[JFMeViewController alloc] init];
        [self addChildViewController:meVC title:@"个人" imageName:@"toolbar_me" selectedImageName:@"toolbar_me_sel"];
    }
    
    - (void)addChildViewController:(UIViewController *)childViewController title:(NSString *)title imageName:(NSString *)imageName selectedImageName:(NSString *)selectedImageName {
        childViewController.title = title;
        childViewController.tabBarItem.image = [UIImage imageNamed:imageName];
        childViewController.tabBarItem.selectedImage = [[UIImage imageNamed:selectedImageName] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
        UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:childViewController];
        [self addChildViewController:navigationController];
        [self.customTabBar addTabBarButtonWithItem:childViewController.tabBarItem];
    }
    
    //接收到点击中间按钮的通知,present(模态)出控制器
    - (void)presentLiveController {
        JFLiveViewController *jfLiveVC = [[JFLiveViewController alloc] init];
        [self presentViewController:jfLiveVC animated:YES completion:nil];
    }
    
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    
    //  移除通知
    - (void)dealloc {
        [[NSNotificationCenter defaultCenter] removeObserver:self];
    }
    @end
    

    说了这么多,如果你也只是需要三个控制器,其实你只需要做这些:
    1、下载JFTabBarController源码,解压将JFTabBarController文件夹中文件直接拖入你的xcode项目工程中。
    2、在AppDelegate.m文件中JFTabBarController设为window的根控制器。

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
        self.window.backgroundColor = [UIColor whiteColor];
        self.window.rootViewController = [[JFTabBarController alloc] init];
        [self.window makeKeyAndVisible];
        return YES;
    }
    

    3、重写JFTabBarcontroller.m文件中-(void)addAllChildViewControllers函数,添加子控制器
    4、JFTabBarClickMiddleButtonDidNotification通知,
    重写JFTabBarcontroller.m文件中- (void)presentLiveController方法。
    你需要做的就这四步!

    相关文章

      网友评论

        本文标题:iOS开发之自定义TabBarController-prese

        本文链接:https://www.haomeiwen.com/subject/htgzettx.html