你所不知道的UITabBarButton?

作者: DXSmile | 来源:发表于2016-02-19 19:23 被阅读6001次

    项目源码请查看我的GitHub项目地址:

    https://github.com/DXSmile/-Usage-of-UITabBarButton-.git

    对于KVC可以更改私有属性的一些补充,

    http://www.jianshu.com/p/40cae3b556ac
    大家看完这篇之后,可以看看这个补充!!!

    摘要:UITabBarButton的相关介绍,已经通过新浪微博实例验证tabBar中间按钮的创建

    阐述:

    只要有一定开发经验的iOS攻城狮,只要你做过应用程序APP的开发,不可避免的都会用到UITabBarController, UITabBarController又称标签控制器 ,同样是管理多控制器的,我们一般的做法都是将多个(一般是4-6个之间)UINavigationController作为UITabBarController的子控件,添加到UITabBarController的导航标签栏(也叫工具条)UITabBar上;

    今天在这里,我要讲的,不是怎样创建一个UITabBarController,因为,这个比较简单,也是每个iOS攻城狮所需要必备的技能,那么问题来了,今天,我要说什么呢 ?

    细心的朋友估计已经看出来了, 没错, 我要讲的是, 在创建UITabBarController的UITabBar标签栏的时候, 容易困扰也容易被大家忽视的UITabBarButton的问题.

    1.什么是UITabBarButton?

    &1.

    我们都知道UITabBarController下方的工具条称为UITabBar ,如果UITabBarController有N个子控制器,那么UITabBar内部就会有N 个UITabBarButton作为子控件与之对应。

    也就是说,UITabBarButton是UITabBarController中各个子控制器在工具条中对应的按钮的称呼,

    同时我们可以注意到一个现象,那就是我们创建好UITabBarButton之后,各个UITabBarButton在UITabBar中的位置是均分的,UITabBar的高度为49。
    如: 我这里有一个创建好的UITabBarController

    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view.
        
        // 创建4个子控制器
        [self setupChildViewController];
    }
    
    #pragma mark - 创建TabBarController的4个子控制器
    // 封装创建TabBarController的4个子控制器的方法
    - (void)setupChildViewController {
        
        // 添加四个TabBarController的子控制器UINavigationController
        // 首页Home
        UINavigationController *navHome = [self navigationControllerWithStoryboardName:@"DXHome"];
        [self setupOneChildViewController:navHome image:[UIImage imageNamed:@"tabbar_home"] selectedImage:[UIImage imageWithOriginalName:@"tabbar_home_selected"] title:@"首页"];
        
        // 消息message
        UINavigationController *navMessage = [self navigationControllerWithStoryboardName:@"DXMessage"];
        [self setupOneChildViewController:navMessage image:[UIImage imageNamed:@"tabbar_message_center"] selectedImage:[UIImage imageWithOriginalName:@"tabbar_message_center_selected"] title:@"消息"];
    
        // 发现discover
        UINavigationController *navDiscover = [self navigationControllerWithStoryboardName:@"DXDiscover"];
        [self setupOneChildViewController:navDiscover image:[UIImage imageNamed:@"tabbar_discover"] selectedImage:[UIImage imageWithOriginalName:@"tabbar_discover_selected"] title:@"发现"];
    
        // 我profile
        UINavigationController *navProfile = [self navigationControllerWithStoryboardName:@"DXProfile"];
        [self setupOneChildViewController:navProfile image:[UIImage imageNamed:@"tabbar_profile"] selectedImage:[UIImage imageWithOriginalName:@"tabbar_profile_selected"] title:@"我"];
        
        // 添加到tabBar
        self.viewControllers = @[navHome, navMessage, navDiscover, navProfile];
    
    }
    
    #pragma mark - 创建一个子控制器的方法
    // 封装创建一个子控制器的方法
    - (void)setupOneChildViewController:(UIViewController *)vc image:(UIImage *)image selectedImage:(UIImage *)selectedImage title:(NSString *)title {
      
        vc.tabBarItem.image = image;
        vc.tabBarItem.selectedImage = selectedImage;
        vc.tabBarItem.badgeValue = @"10";
        vc.tabBarItem.title = title;
    }
    
    #pragma mark - 封装通过storyboard创建NavigationController的方法
    // 封装通过storyboard创建NavigationController的方法
    - (UINavigationController *)navigationControllerWithStoryboardName:(NSString *)name {
        // 1. 加载storyboard文件
        UIStoryboard *storyboard = [UIStoryboard storyboardWithName:name bundle:nil];
        // 2. 创建Storyboard中的初始化控制器
        return [storyboard instantiateInitialViewController];
    }
    
    
    

    运行出来之后,效果是这样的:


    自定义tabBar

    通过,输出结果,可以看出, 我们已经成功的更改了tabBar的权限,改为了,我们自定义的tabBar, 那么此时我们需要来验证一下,是否还可以拿到UITabBarButton;

    同样调用之前的方法: 这里我们在另一个方法中来测试,

    // 系统在即将开始为view准备控件的时候调用这个方法
    - (void)viewWillAppear:(BOOL)animated {
        [super viewWillAppear:animated];
        NSLog(@"%@", self.tabBar.subviews);
    }
    

    输出结果为:


    自定义之后重新验证UITabBarButton

    那么接下来,我们就可以开始写代码了:

    //  DXTabBar.m
    //  DXSWeibo
    //  Created by xiongdexi on 16/2/19.
    //  Copyright © 2016年 DXSmile. All rights reserved.
    //
    
    #import "DXTabBar.h"
    @interface DXTabBar ()
    // 定义中间按钮的属性
    @property (nonatomic, weak) UIButton *plusButton;
    @end
    
    @implementation DXTabBar
    #pragma mark - 懒加载设置中间按钮 保证只有一个
    - (UIButton *)plusButton {
       if (_plusButton == nil) {
           // 1.根据自定义类型初始化一个button
           UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
           // 2.设置btn的各状态的图片属性
           [btn setImage:[UIImage imageNamed:@"tabbar_compose_icon_add"] forState:UIControlStateNormal];
           [btn setImage:[UIImage imageNamed:@"tabbar_compose_icon_add_highlighted"] forState:UIControlStateHighlighted];
           [btn setBackgroundImage:[UIImage imageNamed:@"tabbar_compose_button"] forState:UIControlStateNormal];
           [btn setBackgroundImage:[UIImage imageNamed:@"tabbar_compose_button_highlighted"] forState:UIControlStateHighlighted];
           // 3. 设置btn按钮的尺寸和图片的默认大小一样大
           [btn sizeToFit];
           
           // 4. 把按钮赋值给_plusButton
           _plusButton = btn;
           
           // 5. 把按钮添加到tabBar中 ,建立强引用
           [self addSubview:_plusButton];
       } 
       return _plusButton;
    }
    
    #pragma mark - 调整子控件的位置和尺寸
    // 调整子控件的位置和尺寸
    - (void)layoutSubviews {
       [super layoutSubviews];
       CGFloat w = self.bounds.size.width;
       CGFloat h = self.bounds.size.height;
       
       CGFloat butX = 0;  // x 是不确定的,可以初始化为0
       CGFloat butY = 0;  // y 就是0
       CGFloat butW = w / (self.items.count + 1); // 有几个UITabBarButton就有几个items模型
       CGFloat butH = h;
       
       int i = 0; // 定义角标,初始化为0
       // 调整系统自带的tabBar上面的按钮的位置
       for (UIView *tabBarButton in self.subviews) {
           // 判断是否是UITabBarButton
           if ([tabBarButton isKindOfClass:NSClassFromString(@"UITabBarButton")]) {
               
               // 因为中间需要预留一个位置,所以,当i到中间的是,就跳过
               if (i == 2) {
                   i = 3;
               }
               butX = i * butW;  
               tabBarButton.frame = CGRectMake(butX, butY, butW, butH);
               i++;
           }
       }
    
       // 设置中间按钮的位置
       self.plusButton.center = CGPointMake(w * 0.5, h * 0.5);
    }
    

    效果图:

    中间按钮效果图

    相关文章

      网友评论

      • 宋鸿康iOS:文章中的图片显示不出来了...
      • again_onceagain:需要适配 ipad 怎么办/
      • 超_iOS:我在一个传智的教学视频中看过一样的代码.不过那又怎样.学习了
        DXSmile:@_超 嗯我也是以前学过
      • Sanchain:请问这个item的title font可以改吗
      • Jimm_鱼:看了这边文章,就知道楼主肯定是李明杰的徒弟了。 :smile:
      • 烟佛经:图片不见了,,,关于tabbarbutton中的图片适配是怎么解决的啊,里面的图片是20*20的么?>?/
        DXSmile:@烟佛经 图片的适配问题, 你要根据tabbarbutton的自身来设置, 因为这里面是自定义了, 更换了tabbarbutton, 所以需要里面的图片也是合适的尺寸, 这个切图, 用一般UI给的 就可以的
      • 程小曦:好像是李明杰的那个思路,不过这个没有根本解决tabbbar上面的按钮对象的动画问题,自定义的还不够彻底
        DXSmile:@程小曦 是的 这个自定义目前还不彻底, 还需要进一步自定义, 因为这里是采用了修改私有方法的取巧办法, 还不是真正意义上的自定义
      • iOS_小绅士:你好.我把tabbarItem 换成了三个.左右两个是add的.中间的是利用自定义的UItabbar加的一个按钮.然后平分分布.但我发现.第一个按钮的点击区域始终占据了tabbar的一半宽度...这个问题你有遇到吗楼主
        DXSmile:@iOS_小绅士 你好 如果你是要做三个tabBarItem的话 你应该将屏幕一分为三, 左右两个用自定义的tabBarItem, 而中间的 可以加一个按钮, 用这样的方式, 就可以让每个按钮都平分了
      • 云画的跃光:你好,我想请问下,在ipad上,那四个tabbarbutton是不是也是平均分布的?我的是集中在中间
        云画的跃光:@DXSmile 嗯,知道了
        DXSmile:@云画的跃光 在iPad上 你需要做适配, 监听屏幕的旋转, 这样才能做到iPad的正取显示
      • 云画的跃光:你好,我想请教你一个问题
      • goSLEEP:楼主 封装通过storyboard创建NavigationController的方法这个怎么理解啊 我运行的时候DXHome 我得改成Main吗
        goSLEEP:@DXSmile 我的是Main.storyboard 我用你的源代码运行 报了个错: 找不到一个故事板名为“DXHome”包NSBundle..... 我把DXHome 改成Main 又爆说:找不到DXMessage :cry:
        DXSmile:@goSLEEP 不需要改动了,我demo里面使用的就是DXHome. storyboard作为的首页的, 你可以在DXTabBarController类中的初始化tabBar的方法setupChildViewController看到
      • liwb:UITabBarButton 既然是私有API,调用的话,Appstore审核会通过吗?
        DXSmile:@liwb 私有属性,调用系统的私有属性,审核是过不了的, 但是如果是我们自己写的类里面的某个私有属性, 这样是没问题的
      • 随风踏叶:这样做,启动后,第一个button就不是选中状态的图片了,楼主是否注意到这个问题
        DXSmile:@随风踏叶 默认第一个选中,这个比较简单,加两句代码即可,我这里就没有写
      • 74af7fee08fd:是这样的 我按照这种方法在UITabBar里面添加了两个自定义按钮UIButton,但是有一个UIButton按钮点击之后触发的始终是他旁边的UITabBarButton,这个着实非常费解,希望能给写思路
        DXSmile:@简单不花俏 一般来说如果是自定义TabBar,都会全部使用自定义的,如果你是自定义部分item,那你需要拦截TabBar布局和赋值的两个方法,用索引判断拿到你需要的那个item,这样应该就可以了,不过这样的自定义一般很少用到,你可以尝试一下
        74af7fee08fd:@DXSmile 你没明白我的意思 我意思是底部有四个按钮 左边两个是UITabBarButton 就是系统自带的 右边两个是 我用UIButton 自定义的 没有中间那个 + 号
        DXSmile:@简单不花俏 你是直接使用的我的源码吗? 如果是的话, 你可以在里面DXTabBar.m文件中的layoutSubviews方法中,找到一行判断, 当索引为2的时候,就跳过,设置为3 , 这样做的目的是为了单独做底部中间的 + 号按钮, 你可以看一下, 这里是新浪微博的非常巧妙的地方,
      • 玉松:请问如果项目中用到了UITabBarButton 能通过苹果审核吗?谢谢
        Jimm_鱼:@玉松 楼主也不知道,因为没试过苹果审核,这边文章基本上都是李明杰讲课的视频里面原文的。
      • 小時間光:博主,图片都挂掉了,什么情况。
        DXSmile:@漓纤墨 :blush: 有时候浏览器是这样的
        小時間光:@DXSmile Safari 抽风了,换Chrome一点问题都没有。 :cold_sweat:
        DXSmile:@漓纤墨 都可以显示的 亲 :blush:
      • 努努Nunu:深夜福利
      • MrFire_:不错不错,学习了!
        DXSmile:@hungryBoy :blush:
      • SeanCST:你好,这个例子中的UITabBar中的UITabBarButton的subviews中貌似只有UITabBarSwappableImage和ViewUITabBarButtonLabel两个类的对象了,而没有UITabBarSelectionIndicatorView这个“选中”的属性了,那么如何根据获取是否选中的状态呢?比如需要根据选中状态修改ViewUITabBarButtonLabel中文字的颜色,如何实现呢?谢谢
        DXSmile:@DXSmile 当然也还有其他的方法的,我这里只是给你提供一个思路, 好像还有一种方法也可以, 那就是统一设置整个状态栏的属性, 但是这个方式下所有的状态都会是一种, 如果你需要再单独设置的话,如果将item的状态设置为UIButtonTypeCustom自定义模式,这样就可以独立设置,
        DXSmile:@肖恩Sean 首先很抱歉没有及时回复你,主要是这几天比较忙一些, 对于你提出的问题, 如何修改选中状态下的tabBarButton的属性, 这里你可以调用tabBar的代理方法来实现:<DXTabBarDelegate>, 比如这个代理里面的- (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item { } 这个方法, 就是在选中状态下的tabBarItem需要做的事情, 还有一种方法就是: 自定义tabBar类,使用你预先设置要的图片来代替,然后更改图片的渲染模式为原始模式:UIImageRenderingModeAlwaysOriginal, 这样同样可以达到效果, 这两种方式,你都可以尝试一下
      • Senior丶:正好需要这个,半夜能看到,实在是兴奋的不想睡了:heart_eyes::heart_eyes::heart_eyes:
        Senior丶:@DXSmile 想问一下 这个的图片的尺寸是不是固定的,能不能给个联系方式
        DXSmile:@Senior丶 :blush: 能对你有帮助就好, 如果不妥的地方,还望指正啊 :smiley:
      • 73e81a42ef46:为什么会写的这么好呢,:scream:
        DXSmile:@73e81a42ef46 呃 没有写好呢, 都被别人说没有原创性呢 :blush:
      • 蓝翔:我只能说培训机构教得好,连发个文章,都原文抄袭
        蓝翔:@DXSmile 只是说你写的东西没有原创性,并不是攻击谁,你自己去看下,类似的文章代码,简书github coding都是这些代码。
        蓝翔:@DXSmile 没有攻击你好吗? 真是小孩子。
        DXSmile:@蓝翔 我不知道你这话从何说起, 也不知道你为什么喜欢攻击人, 如果你不喜欢我发的文章, 你可以默默的离开, 不管培训机构出来的也好, 还是实际工作总结出来的也好, 我们围绕的是知识点的分享和学习, 关注的也只是技术, 或者说提升自己, 这篇文章,我非常用心的整理,也确实借鉴了之前在培训机构学习时候的一些代码和图片, 我只是想阐述明白这个知识点而已, 这有什么错吗???
        再者说了, 我们的出身确实是通过培训机构出来的, 但那又怎么了? 我们在培训机构培训那几个月, 比我再大学计算机专业几年学得东西都要多,都要用心, 都要实用, 而且当我出来工作的时候, 我就很感谢很感恩我在培训机构培训的那几个月, 没有那几个月, 也就没有我现在这么高的收入, 我为我曾经能够有幸去参加培训机构的培训而自豪!!!
        我不知道你为什么看不起培训机构, 我猜你也没有经历过正规的培训吧, 所以,你有这些怨气, 我也表示理解, 一句话结束我和你的对话: 你爱怎么说就怎么说吧, 你高兴就好!!! :blush:
      • Lonely__M:好东西,默默点个赞
        DXSmile:@Lonely__ 谢谢谢谢,多谢你的认同 :blush:
      • 明雨夏:写得很好:+1::+1::+1:
        DXSmile:@明雨夏 多谢多谢, :blush:
      • 6d9f6aa3a9d4:写的不错
        DXSmile:@yeBlueColor 多谢多谢,我还有很多不足,也需要继续探究的, :blush:
      • 黄晓坚:很棒,学习了。
        DXSmile:@黄晓坚 :blush: 共勉共勉
      • 7d9b4d7d8d6c:kvc改readonly是啥原理
        DXSmile:@Listen小华哥 上架并不会影响的
        7d9b4d7d8d6c:@DXSmile 那会影响上架嘛?
        DXSmile:@Listen小华哥 KVC做的事情,就是根据key值,给value值, 这里用KVC来更改tabBar的readonly权限,就相当于我们重新给tabBar设定了一个新的key值,从而达到修改权限的目的. 其实这个方法是有点打苹果系统擦边球的意思, 对于苹果来说,他们是不允许我们这样做的, 这里只是取巧
      • voidxin:八错八错
      • DXSmile:http://www.jianshu.com/collection/8f1ac0fd7ce4 你们也可以关注我们的"iOS移动开发社区" 这个专题, 里面收录了不少优秀的帖子,
      • iOS程序犭袁:学习下
        DXSmile:@iOS程序犭袁 共勉共勉 :blush:
      • tyj_yy:非常好
        DXSmile:@tyj_yy 谢谢夸奖 :smiley:
      • CaiYue_:谢谢,正需
        DXSmile:@SoledadMe 能对你有帮助就好 :smiley:
      • 李大戮:大赞
        DXSmile:@李大帅 :blush: 这篇的源码我会抽时间继续完善的,到时候请大家斧正

      本文标题:你所不知道的UITabBarButton?

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