美文网首页iOSiOS开发者
iOS OC-自定义TabBar TabBarViewContr

iOS OC-自定义TabBar TabBarViewContr

作者: Hedgehog___ | 来源:发表于2018-07-26 14:55 被阅读102次

      前段时间,我们产品同学又提了个需求。咳咳,就是想要服务器动态控制tabBar的图片和文字,而且要兼容文字没有的情况下图片撑满,而且图片的显示范围固定。但是系统自带的tabBarItem我试了下是不能固定图片显示范围的,它是根据图片的大小来适应的。所有我就自定义了一套,最终效果如下(最后有demo地址):


    QQ20180726-134906-HD.gif
    1、自定义tabBarItem
    @interface CYXTabBarItem : UIView
    /*未选中的图片*/
    @property (nonatomic,strong) UIImage *image;
    /*选中的图片*/
    @property (nonatomic,strong) UIImage *selectedImage;
    /*标题*/
    @property (nonatomic,copy) NSString *title;
    /*是否是选中*/
    @property (nonatomic,assign) BOOL selected;
    /*最大图片尺寸*/
    @property (nonatomic,assign) CGSize maxImageSize;
    /*最小图片尺寸*/
    @property (nonatomic,assign) CGSize minImageSize;
    /*文字颜色*/
    @property (nonatomic,strong) UIColor *titleColor;
    /*选中的文字颜色*/
    @property (nonatomic,strong) UIColor *selectedTitleColor;
    /*点击*/
    @property (nonatomic,strong) void(^selectBlock)(void);
    /*更新布局方法 设置完之后记得调用*/
    -(void)updateImageAndTitle;
    @end
    

    implementation:

    @interface CYXTabBarItem()
    /*图片*/
    @property (nonatomic,strong) UIImageView *imageView;
    /*文字*/
    @property (nonatomic,strong) UILabel *titleLabel;
    @end
    @implementation CYXTabBarItem
    - (instancetype)initWithFrame:(CGRect)frame
    {
        self = [super initWithFrame:frame];
        if (self) {
            [self addSubview:self.imageView];
            [self addSubview:self.titleLabel];
            [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
                make.height.mas_equalTo(11);
                make.left.and.right.equalTo(self);
                make.top.equalTo(self).offset(35);
            }];
            __weak __typeof(self) _self = self;
            [self setTapActionWithBlock:^{
                if (_self.selectBlock) {
                    _self.selectBlock();
                }
            }];
        }
        return self;
    }
    /*更新布局方法 设置完之后记得调用*/
    -(void)updateImageAndTitle{
        self.titleLabel.text = self.title;
        if (self.selected) {
            self.titleLabel.font = [UIFont systemFontOfSize:10.0];
            self.titleLabel.textColor = self.selectedTitleColor;
            if (self.selectedImage) {
                self.imageView.image = self.selectedImage;
            }
        }else{
            self.titleLabel.font = [UIFont boldSystemFontOfSize:10.0];
            self.titleLabel.textColor = self.titleColor;
            if (self.image) {
                self.imageView.image = self.image;
            }
        }
        if ([self.title length]) {
            [self.imageView mas_remakeConstraints:^(MASConstraintMaker *make) {
                make.height.and.width.mas_equalTo(22);
                make.centerX.equalTo(self);
                make.top.equalTo(self).offset(5);
            }];
        }else{
            [self.imageView mas_remakeConstraints:^(MASConstraintMaker *make) {
                make.height.and.width.mas_equalTo(40);
                make.centerX.equalTo(self);
                make.top.equalTo(self).offset(5);
            }];
        }
    }
    #pragma mark ---G
    -(UIImageView*)imageView{
        if(!_imageView){
            _imageView = [[UIImageView alloc] init];
        }
        return _imageView;
    }
    -(UILabel*)titleLabel{
        if(!_titleLabel){
            _titleLabel = [[UILabel alloc] init];
            _titleLabel.font = [UIFont systemFontOfSize:10];
            _titleLabel.textColor = [UIColor grayColor];
            _titleLabel.textAlignment = NSTextAlignmentCenter;
        }
        return _titleLabel;
    }
    
    2、自定义tabBarView
    @interface CYXBarView : UIView
    
    /*初始化按钮*/
    -(void)initButtonWithViewControllers:(NSArray<UIViewController *> * )viewControllers;
    /*最大图片尺寸*/
    @property (nonatomic,assign) CGSize maxImageSize;
    /*最小图片尺寸*/
    @property (nonatomic,assign) CGSize minImageSize;
    /*文字颜色*/
    @property (nonatomic,strong) UIColor *titleColor;
    /*选中的文字颜色*/
    @property (nonatomic,strong) UIColor *selectedTitleColor;
    /*点击*/
    @property (nonatomic,strong) void(^selectBlock)(NSInteger index);
    @property (nonatomic, assign) NSInteger selectIndex;
    @end
    

    implementation:

    @interface CYXBarView()
    
    
    @property (nonatomic,strong) NSMutableArray<CYXTabBarItem *> *items;
    @end
    @implementation CYXBarView
    - (instancetype)initWithFrame:(CGRect)frame
    {
        self = [super initWithFrame:frame];
        if (self) {
            self.maxImageSize = CGSizeMake(40, 40);
            self.minImageSize = CGSizeMake(20, 20);
            self.titleColor = [UIColor grayColor];
            self.selectedTitleColor = [UIColor redColor];
            self.items = [NSMutableArray new];
        }
        
        return self;
    }
    
    -(void)initButtonWithViewControllers:(NSArray<UIViewController *> * )viewControllers{
        [self.items removeAllObjects];
        
        for (UIView * view in self.subviews) {
            [view removeFromSuperview];
        }
        CGFloat  itemWidth =screenWidth/viewControllers.count;
        for (int i= 0; i<viewControllers.count; i++) {
            CYXTabBarItem * item = [[CYXTabBarItem alloc] init];
            item.maxImageSize = self.maxImageSize;
            item.minImageSize = self.minImageSize;
            item.titleColor = self.titleColor;
            item.selectedTitleColor = self.selectedTitleColor;
            UIViewController * viewController = viewControllers[i];
            item.title = [viewController.tabBarItem.title length]?viewController.tabBarItem.title:viewController.title;
            item.selectedImage = viewController.tabBarItem.selectedImage;
            item.image = viewController.tabBarItem.image;
            [self addSubview:item];
            [item mas_makeConstraints:^(MASConstraintMaker *make) {
                make.width.mas_equalTo(itemWidth);
                make.height.equalTo(self);
                make.top.equalTo(self);
                make.left.mas_equalTo(i*itemWidth);
            }];
            
            [self.items addObject:item];
            __weak __typeof(self) _self = self;
            item.selectBlock = ^{
                _self.selectIndex = i;
                if (_self.selectBlock) {
                    _self.selectBlock(_self.selectIndex);
                }
            };
            [item updateImageAndTitle];
        }
        self.selectIndex = 0;
    }
    - (void)setSelectIndex:(NSInteger)selectIndex
    {
        if (![self.items count]||selectIndex>=[self.items count]) {return;}
        // 先把上次选择的item设置为可用
        CYXTabBarItem *lastItem = self.items[_selectIndex];
        lastItem.selected = NO;
        // 再把这次选择的item设置为不可用
        CYXTabBarItem *item = self.items[selectIndex];
        item.selected = YES;
        _selectIndex = selectIndex;
        [lastItem updateImageAndTitle];
        [item updateImageAndTitle];
    }
    @end
    
    2、自定义tabBar
    @class CYXBarView;
    @interface CYXTabBar : UITabBar
    
    @property (nonatomic,strong) CYXBarView *tabBarView;
    
    @end
    
    

    implementation:

    @interface CYXTabBar ()
    
    @end
    @implementation CYXTabBar
    - (instancetype)initWithFrame:(CGRect)frame
    {
        self = [super initWithFrame:frame];
        if (self) {
            [self addSubview:self.tabBarView];
            [self.tabBarView mas_makeConstraints:^(MASConstraintMaker *make) {
                make.top.and.right.and.left.and.bottom.equalTo(self);
            }];
            
        }
        
        return self;
    }
    - (void)layoutSubviews
    {
        [super layoutSubviews];
        // 把tabBarView带到最前面,覆盖tabBar的内容
        [self bringSubviewToFront:self.tabBarView];
        /*隐藏原来的*/
        for (UIView *view in self.subviews) {
            if ([view isKindOfClass:NSClassFromString(@"UITabBarButton")]) {
                view.hidden = YES;
            }
        }
        
    }
    // 重写hitTest方法,让超出tabBar部分也能响应事件
    - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
    {
        if (self.clipsToBounds || self.hidden || (self.alpha == 0.f)) {
            return nil;
        }
        UIView *result = [super hitTest:point withEvent:event];
        // 如果事件发生在tabbar里面直接返回
        if (result) {
            return result;
        }
        // 这里遍历那些超出的部分就可以了,不过这么写比较通用。
        for (UIView *subview in self.tabBarView.subviews) {
            // 把这个坐标从tabbar的坐标系转为subview的坐标系
            CGPoint subPoint = [subview convertPoint:point fromView:self];
            result = [subview hitTest:subPoint withEvent:event];
            // 如果事件发生在subView里就返回
            if (result) {
                return result;
            }
        }
        return nil;
    }
    #pragma mark ---G
    -(CYXBarView*)tabBarView{
        if(!_tabBarView){
            _tabBarView = [[CYXBarView alloc] init];
        }
        return _tabBarView;
    }
    
    2、自定义UITabBarController
    @interface CYXTabBarViewController : UITabBarController
    
    @end
    

    implementation:

    @interface CYXTabBarViewController ()
    @property (nonatomic,strong) CYXTabBar *customTabBar;
    @end
    
    @implementation CYXTabBarViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view.
        [self setValue:self.customTabBar forKey:@"tabBar"];
        
        [self initViewControllers];
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            self.selectedIndex = 3;
        });
    }
    -(void)initViewControllers{
        NSMutableArray * viewControllers = [NSMutableArray new];
        UIViewController *homeVC = [[UIViewController alloc] init];
        homeVC.view.backgroundColor = [UIColor redColor];
        [viewControllers addObject:[self addChildViewController:homeVC title:@"首页" imageNamed:@"tabBar_home"]];
        
        UIViewController *expoVC = [[UIViewController alloc] init];
        expoVC.view.backgroundColor = [UIColor yellowColor];
        [viewControllers addObject:[self addChildViewController:expoVC title:@"家博会" imageNamed:@"tabBar_activity"]];
        
        UIViewController *activityVC = [[UIViewController alloc] init];
        activityVC.view.backgroundColor = [UIColor yellowColor];
        [viewControllers addObject:[self addChildViewController:activityVC title:@"" imageNamed:@"tabBar_activity"]];
        
        UIViewController *findVC = [[UIViewController alloc] init];
        findVC.view.backgroundColor = [UIColor blueColor];
        [viewControllers addObject:[self addChildViewController:findVC title:@"发现" imageNamed:@"tabBar_find"]];
        
        UIViewController *mineVC = [[UIViewController alloc] init];
        mineVC.view.backgroundColor = [UIColor greenColor];
        [viewControllers addObject:[self addChildViewController:mineVC title:@"我的" imageNamed:@"tabBar_mine"]];
        
        self.viewControllers = viewControllers;
    }
    // 添加某个 childViewController
    - (UINavigationController *)addChildViewController:(UIViewController *)vc title:(NSString *)title imageNamed:(NSString *)imageNamed
    {
        UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc];
        // 如果同时有navigationbar 和 tabbar的时候最好分别设置它们的title
        vc.navigationItem.title = title;
        nav.tabBarItem.title = title;
        nav.tabBarItem.image = [UIImage imageNamed:imageNamed];
        nav.tabBarItem.selectedImage = [UIImage imageNamed:@"jmtIconBg"];
        return nav;
    }
    
    -(void)setViewControllers:(NSArray<__kindof UIViewController *> *)viewControllers{
        [super setViewControllers:viewControllers];
        [self.customTabBar.tabBarView initButtonWithViewControllers:viewControllers];
    }
    -(void)setSelectedIndex:(NSUInteger)selectedIndex{
        [super setSelectedIndex:selectedIndex];
        self.customTabBar.tabBarView.selectIndex = selectedIndex;
    }
    #pragma mark ---G
    -(CYXTabBar*)customTabBar{
        if(!_customTabBar){
            _customTabBar = [[CYXTabBar alloc] init];
            __weak __typeof(self) _self = self;
            _customTabBar.tabBarView.selectBlock = ^(NSInteger index) {
                 _self.selectedIndex = index;
            };
        }
        return _customTabBar;
    }
    

    Appdelegate:

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        // Override point for customization after application launch.
        self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
        self.window.backgroundColor = [UIColor whiteColor];
        self.window.rootViewController = [[CYXTabBarViewController alloc] init];
        // 设置这个窗口有主窗口并显示
        [self.window makeKeyAndVisible];
        return YES;
    }
    

    这样就实现上图所示效果图了,高度自定义化,可随意修改。欢迎讨论指教
    demo:https://github.com/SionChen/CYXCustomTabBarController

    相关文章

      网友评论

        本文标题:iOS OC-自定义TabBar TabBarViewContr

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