zoukankan      html  css  js  c++  java
  • 自定义的TabBar

    这是一个老生常谈的就问题,写在这里只是为了做一下笔记

    实现类似下图的问题

    废话不多说,直接上代码

    首先自定义一个tabbar 继承与 UITabBar

    .h

    #import <UIKit/UIKit.h>
    //tab页面个数
    typedef NS_ENUM(NSInteger, SamItemUIType) {
        SamItemUIType_Three = 3,//底部3个选项
        SamItemUIType_Five = 5,//底部5个选项
    };
    @class BaseTabBar;
    @protocol SamTabBarDelegate <NSObject>
    
    -(void)tabBar:(BaseTabBar *)tabBar clickCenterButton:(UIButton *)sender;
    
    @end
    
    @interface BaseTabBar : UITabBar
    @property (nonatomic, weak) id<SamTabBarDelegate> tabDelegate;
    @property (nonatomic, strong) NSString *centerBtnTitle;
    @property (nonatomic, strong) NSString *centerBtnIcon;
    
    +(instancetype)instanceCustomTabBarWithType:(SamItemUIType)type;
    
    @end

    .m

    #import "BaseTabBar.h"
    @interface BaseTabBar()
    @property(nonatomic, strong) UIButton *centerButton;
    @property(nonatomic, strong) UILabel *centerTitle;
    @property (nonatomic,assign) SamItemUIType type;
    @end
    @implementation BaseTabBar
    
    +(instancetype)instanceCustomTabBarWithType:(SamItemUIType)type{
        BaseTabBar *tabBar = [[BaseTabBar alloc] init];
        tabBar.type = type;
        return tabBar;
    }
    
    -(instancetype)initWithFrame:(CGRect)frame{
        self = [super initWithFrame:frame];
        if (self) {
            self.translucent = NO;
            UIButton *plusBtn = [UIButton buttonWithType:UIButtonTypeCustom];
            self.centerButton = plusBtn;
            [plusBtn addTarget:self action:@selector(plusBtnDidClick) forControlEvents:UIControlEventTouchUpInside];
            [self addSubview:plusBtn];
            
            UILabel *lblTitle = [[UILabel alloc] init];
            self.centerTitle = lblTitle;
            lblTitle.font = [UIFont systemFontOfSize:10];
            lblTitle.textColor = [UIColor blackColor];
            lblTitle.textAlignment = NSTextAlignmentCenter;
            [self addSubview:lblTitle];
            
        }
        return self;
    }
    
    -(void)plusBtnDidClick{
        if (self.tabDelegate && [self.tabDelegate respondsToSelector:@selector(tabBar:clickCenterButton:)]) {
            [self.tabDelegate tabBar:self clickCenterButton:self.centerButton];
        }
    }
    
    // 调整子视图的布局
    -(void)layoutSubviews{
        [super layoutSubviews];
        CGFloat width = self.frame.size.width/self.type;
        Class class = NSClassFromString(@"UITabBarButton");
        for (UIView *view in self.subviews) {
            if ([view isEqual:self.centerTitle]) {//self.centerButton
                view.frame = CGRectMake(0, 0, width, 15);
                view.center = CGPointMake(self.frame.size.width/2, self.frame.size.height - view.frame.size.height + 8);
            }else if ([view isEqual:self.centerButton]) {//self.centerButton
                view.frame = CGRectMake(0, 0, width, self.frame.size.height);
                [view sizeToFit];
                view.center = CGPointMake(self.frame.size.width/2, 10);
            }else if ([view isKindOfClass:class]){//system button
                CGRect frame = view.frame;
                int indexFromOrign = view.frame.origin.x/width;//防止UIView *view in self.subviews 获取到的不是有序的
                if (indexFromOrign >= (self.type - 1) / 2) {
                    indexFromOrign++;
                }
                CGFloat x = indexFromOrign * width;
                //如果是系统的UITabBarButton,那么就调整子控件位置,空出中间位置
                view.frame = CGRectMake(x, view.frame.origin.y, width, frame.size.height);
                
                //调整badge postion
                for (UIView *badgeView in view.subviews){
                    NSString *className = NSStringFromClass([badgeView class]);
                    // Looking for _UIBadgeView
                    if ([className rangeOfString:@"BadgeView"].location != NSNotFound){
                        badgeView.layer.transform = CATransform3DIdentity;
                        badgeView.layer.transform = CATransform3DMakeTranslation(-17.0, 1.0, 1.0);
                        break;
                    }
                }
            }
        }
    }
    
    
    -(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
        //这一个判断是关键,不判断的话push到其他页面,点击发布按钮的位置也是会有反应的,这样就不好了
        //self.isHidden == NO 说明当前页面是有tabbar的,那么肯定是在导航控制器的根控制器页面
        //在导航控制器根控制器页面,那么我们就需要判断手指点击的位置是否在发布按钮身上
        //是的话让发布按钮自己处理点击事件,不是的话让系统去处理点击事件就可以了
        if (self.isHidden == NO) {
            //将当前tabbar的触摸点转换坐标系,转换到发布按钮的身上,生成一个新的点
            CGPoint newP = [self convertPoint:point toView:self.centerButton];
            
            //判断如果这个新的点是在发布按钮身上,那么处理点击事件最合适的view就是发布按钮
            if ( [self.centerButton pointInside:newP withEvent:event]) {
                return self.centerButton;
            }else{//如果点不在发布按钮身上,直接让系统处理就可以了
                return [super hitTest:point withEvent:event];
            }
        }
        else {//tabbar隐藏了,那么说明已经push到其他的页面了,这个时候还是让系统去判断最合适的view处理就好了
            return [super hitTest:point withEvent:event];
        }
    }
    
    -(void)setCenterBtnIcon:(NSString *)centerBtnIcon{
        _centerBtnIcon = centerBtnIcon;
        [self.centerButton setBackgroundImage:[UIImage imageNamed:self.centerBtnIcon] forState:UIControlStateNormal];
        [self.centerButton setBackgroundImage:[UIImage imageNamed:self.centerBtnIcon] forState:UIControlStateHighlighted];
    }
    
    -(void)setCenterBtnTitle:(NSString *)centerBtnTitle{
        _centerBtnTitle = centerBtnTitle;
        self.centerTitle.text = centerBtnTitle;
    }
    
    @end

    然后写一个继承与UITabBarController的Controller

    #import "RootTabBarViewController.h"
    #import "BaseTabBar.h"
    #import "FirstViewController.h"
    #import "BaseNaViewController.h"
    #import "SecondViewController.h"
    #import "UITabBar+BadgeOfTabBar.h"
    @interface RootTabBarViewController ()<SamTabBarDelegate>
    
    @end
    
    @implementation RootTabBarViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        [self setupUI];
    }
    
    -(void)setupUI{
        [self setupVC];
        [[UITabBar appearance] setShadowImage:[UIImage new]];
        //kvo形式添加自定义的 UITabBar
        BaseTabBar *tab = [BaseTabBar instanceCustomTabBarWithType:SamItemUIType_Five];
        tab.centerBtnTitle = @"发布";
        tab.centerBtnIcon = @"icon_toolview_add_normal";
        tab.tabDelegate = self;
        [self setValue:tab forKey:@"tabBar"];
    }
    
    - (void)setupVC{
        [self addChildVc:[[FirstViewController alloc] init] title:@"首页" image:@"four-off" selectedImage:@"four-on"];
        [self addChildVc:[[FirstViewController alloc] init] title:@"发现" image:@"four-off" selectedImage:@"four-on"];
        [self addChildVc:[[FirstViewController alloc] init] title:@"消息" image:@"four-off" selectedImage:@"four-on"];
        [self addChildVc:[[FirstViewController alloc] init] title:@"个人中心" image:@"four-off" selectedImage:@"four-on"];
    }
    
    - (void)addChildVc:(UIViewController *)childVc title:(NSString *)title image:(NSString *)image selectedImage:(NSString *)selectedImage{
        // 设置子控制器的文字(可以设置tabBar和navigationBar的文字)
        childVc.title = title;
        // 设置子控制器的tabBarItem图片
        childVc.tabBarItem.image = [UIImage imageNamed:image];
        // 禁用图片渲染
        childVc.tabBarItem.selectedImage = [[UIImage imageNamed:selectedImage] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
        // 设置文字的样式
        [childVc.tabBarItem setTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColor blackColor]} forState:UIControlStateNormal];
        [childVc.tabBarItem setTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColor redColor]} forState:UIControlStateSelected];
        // 为子控制器包装导航控制器
        BaseNaViewController *navigationVc = [[BaseNaViewController alloc] initWithRootViewController:childVc];
        // 添加子控制器
        [self addChildViewController:navigationVc];
    }
    
    -(void)tabBar:(BaseTabBar *)tabBar clickCenterButton:(UIButton *)sender{
    //    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提示" message:@"点击了中间按钮" preferredStyle:UIAlertControllerStyleAlert];
    //    UIAlertAction *action = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
    //
    //    }];
    //    [alert addAction:action];
    //    [self presentViewController:alert animated:YES completion:nil];
        SecondViewController *sec = [[SecondViewController alloc] init];
        
        
        UIViewController *vc = [self topVC:[UIApplication sharedApplication].keyWindow.rootViewController];
        sec.hidesBottomBarWhenPushed = YES;
        [vc.navigationController pushViewController:sec animated:YES];
    }
    
    - (UIViewController *)topVC:(UIViewController *)rootViewController{
        if ([rootViewController isKindOfClass:[UITabBarController class]]) {
            UITabBarController *tab = (UITabBarController *)rootViewController;
            return [self topVC:tab.selectedViewController];
        }else if ([rootViewController isKindOfClass:[UINavigationController class]]){
            UINavigationController *navc = (UINavigationController *)rootViewController;
            return [self topVC:navc.visibleViewController];
        }else if (rootViewController.presentedViewController){
            UIViewController *pre = (UIViewController *)rootViewController.presentedViewController;
            return [self topVC:pre];
        }else{
            return rootViewController;
        }
    }
    
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    
    /*
    #pragma mark - Navigation
    
    // In a storyboard-based application, you will often want to do a little preparation before navigation
    - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
        // Get the new view controller using [segue destinationViewController].
        // Pass the selected object to the new view controller.
    }
    */
    
    @end

    再写一个子控制器继承与UINavigationController 里面不需要写代码

    为tabbar添加小红点

    为UITabBar 写一个类别

    #import <UIKit/UIKit.h>
    
    @interface UITabBar (BadgeOfTabBar)
    - (void)showBadgeOnItmIndex:(int)index tabbarNum:(int)tabbarNum;
    -(void)hideBadgeOnItemIndex:(int)index;
    - (void)removeBadgeOnItemIndex:(int)index;
    @end
    #import "UITabBar+BadgeOfTabBar.h"
    
    @implementation UITabBar (BadgeOfTabBar)
    - (void)showBadgeOnItmIndex:(int)index tabbarNum:(int)tabbarNum{
        [self removeBadgeOnItemIndex:index];
        //label为小红点,并设置label属性
        UILabel *label = [[UILabel alloc]init]; label.tag = 1000+index;
        label.layer.cornerRadius = 5;
        label.clipsToBounds = YES;
        label.backgroundColor = [UIColor redColor];
        CGRect tabFrame = self.frame;
        //计算小红点的X值,根据第index控制器,小红点在每个tabbar按钮的中部偏移0.1,即是每个按钮宽度的0.6倍
        CGFloat percentX = (index+0.6);
        CGFloat tabBarButtonW = CGRectGetWidth(tabFrame)/tabbarNum;
        CGFloat x = percentX*tabBarButtonW;
        CGFloat y = 0.1*CGRectGetHeight(tabFrame);
        //10为小红点的高度和宽度
        label.frame = CGRectMake(x, y, 10, 10);
        [self addSubview:label];
        //把小红点移到最顶层
        [self bringSubviewToFront:label];
        
    }
    
    -(void)hideBadgeOnItemIndex:(int)index{
        [self removeBadgeOnItemIndex:index];
    }
    - (void)removeBadgeOnItemIndex:(int)index{
        for (UIView*subView in self.subviews) {
            if (subView.tag == 1000+index) {
                [subView removeFromSuperview];
                
            }
        }
        
    }
    
    
    
    @end

    调用方法,在要使用的放引入类别,我这里写在VC里面了

    tabbarNum 指的是有几个Tabbar  index指的是 第几个按钮添加小红点
    [self.tabBarController.tabBar showBadgeOnItmIndex:3 tabbarNum:5];

    over!

  • 相关阅读:
    IDEA 2020.1 使用eclipse快捷键
    IDEA 2020.1 配置自定义Maven
    Maven 下载、安装、设置国内镜像
    IDEA 2020.1 下载、安装、激活
    MySQL 5.5/5.7 zip版 下载、安装、卸载、报错
    JDK8 下载、安装、配置环境变量
    如何在虚拟机VM15中安装W10
    虚拟机的安装,VMware-workstation-full-15.5.1-15018445
    为什么要买云服务器
    输入子系统实现的按键驱动
  • 原文地址:https://www.cnblogs.com/nsjelly/p/9317162.html
Copyright © 2011-2022 走看看