IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    自定义tabBar

    键盘上的舞者发表于 2015-10-05 21:02:05
    love 0

    在做开发的时候,我们经常会感觉到系统自带的东西不要用,比如说UITabBar,那么我们可以去自定义。

    比如像微博,QQ空间那样的应用,中间都有个加号,发表微博,说说的,那么这样的怎么去实现呢?

    自定义一个tabBar继承自系统自带的,然后重写其中的

    - (void)layoutSubviews

    方法。

    #import "HWTabBar.h"
    
    @interface HWTabBar()
    @property (nonatomic, weak) UIButton *plusBtn;
    @end
    
    @implementation HWTabBar
    
    - (id)initWithFrame:(CGRect)frame
    {
        self = [super initWithFrame:frame];
        if (self) {
            // 添加一个按钮到tabbar中
            UIButton *plusBtn = [[UIButton alloc] init];
            [plusBtn setBackgroundImage:[UIImage imageNamed:@"tabbar_compose_button"] forState:UIControlStateNormal];
            [plusBtn setBackgroundImage:[UIImage imageNamed:@"tabbar_compose_button_highlighted"] forState:UIControlStateHighlighted];
            [plusBtn setImage:[UIImage imageNamed:@"tabbar_compose_icon_add"] forState:UIControlStateNormal];
            [plusBtn setImage:[UIImage imageNamed:@"tabbar_compose_icon_add_highlighted"] forState:UIControlStateHighlighted];
            plusBtn.size = plusBtn.currentBackgroundImage.size;
            [plusBtn addTarget:self action:@selector(plusClick) forControlEvents:UIControlEventTouchUpInside];
            [self addSubview:plusBtn];
            self.plusBtn = plusBtn;
        }
        return self;
    }
    
    /**
     *  加号按钮点击
     */
    - (void)plusClick
    {
        // 通知代理
        if ([self.delegate respondsToSelector:@selector(tabBarDidClickPlusButton:)]) {
            [self.delegate tabBarDidClickPlusButton:self];
        }
    }
    
    - (void)layoutSubviews
    {
    #warning [super layoutSubviews] 一定要调用
        [super layoutSubviews];
        
        // 1.设置加号按钮的位置
        self.plusBtn.centerX = self.width * 0.5;
        self.plusBtn.centerY = self.height * 0.5;
        
        // 2.设置其他tabbarButton的位置和尺寸
        CGFloat tabbarButtonW = self.width / 5;
        CGFloat tabbarButtonIndex = 0;
        for (UIView *child in self.subviews) {
            Class class = NSClassFromString(@"UITabBarButton");
            if ([child isKindOfClass:class]) {
                // 设置宽度
                child.width = tabbarButtonW;
                // 设置x
                child.x = tabbarButtonIndex * tabbarButtonW;
    
                // 增加索引
                tabbarButtonIndex++;
                if (tabbarButtonIndex == 2) {
                    tabbarButtonIndex++;
                }
            }
        }
    }
    
    @end

    注意到tabBar中的每个选项卡的类名叫做UITabBarButton。

    当你在UITabBarController中添加选项卡的时候,需要用KVC去修改系统自带的tabBar,只能通过KVC去修改,因为如果直接使用self.tabBar=自定义的,这样会报错,因为tabBar这个属性是readonly也就是只读的,不能直接去修改,但是通过KVC就行,KVC可以修改任何属性!

    //
    //  HWTabBarViewController.m
    //  黑马微博2期
    //
    //  Created by apple on 14-10-7.
    //  Copyright (c) 2014年 heima. All rights reserved.
    //
    
    #import "HWTabBarViewController.h"
    #import "HWHomeViewController.h"
    #import "HWMessageCenterViewController.h"
    #import "HWDiscoverViewController.h"
    #import "HWProfileViewController.h"
    #import "HWNavigationController.h"
    #import "HWTabBar.h"
    
    @interface HWTabBarViewController () <HWTabBarDelegate>
    
    @end
    
    @implementation HWTabBarViewController
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        
        // 1.初始化子控制器
        HWHomeViewController *home = [[HWHomeViewController alloc] init];
        [self addChildVc:home title:@"首页" image:@"tabbar_home" selectedImage:@"tabbar_home_selected"];
        
        HWMessageCenterViewController *messageCenter = [[HWMessageCenterViewController alloc] init];
        [self addChildVc:messageCenter title:@"消息" image:@"tabbar_message_center" selectedImage:@"tabbar_message_center_selected"];
        
        HWDiscoverViewController *discover = [[HWDiscoverViewController alloc] init];
        [self addChildVc:discover title:@"发现" image:@"tabbar_discover" selectedImage:@"tabbar_discover_selected"];
        
        HWProfileViewController *profile = [[HWProfileViewController alloc] init];
        [self addChildVc:profile title:@"我" image:@"tabbar_profile" selectedImage:@"tabbar_profile_selected"];
        
        // 2.更换系统自带的tabbar
        HWTabBar *tabBar = [[HWTabBar alloc] init];
        [self setValue:tabBar forKeyPath:@"tabBar"];
        /*
         [self setValue:tabBar forKeyPath:@"tabBar"];相当于self.tabBar = tabBar;
         [self setValue:tabBar forKeyPath:@"tabBar"];这行代码过后,tabBar的delegate就是HWTabBarViewController
         说明,不用再设置tabBar.delegate = self;
         */
        
        /*
         1.如果tabBar设置完delegate后,再执行下面代码修改delegate,就会报错
         tabBar.delegate = self;
    
         2.如果再次修改tabBar的delegate属性,就会报下面的错误
         错误信息:Changing the delegate of a tab bar managed by a tab bar controller is not allowed.
         错误意思:不允许修改TabBar的delegate属性(这个TabBar是被TabBarViewController所管理的)
         */
    }
    
    /**
     *  添加一个子控制器
     *
     *  @param childVc       子控制器
     *  @param title         标题
     *  @param image         图片
     *  @param selectedImage 选中的图片
     */
    - (void)addChildVc:(UIViewController *)childVc title:(NSString *)title image:(NSString *)image selectedImage:(NSString *)selectedImage
    {
        // 设置子控制器的文字
        childVc.title = title; // 同时设置tabbar和navigationBar的文字
        
        // 设置子控制器的图片
        childVc.tabBarItem.image = [UIImage imageNamed:image];
        childVc.tabBarItem.selectedImage = [[UIImage imageNamed:selectedImage]imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
        
        // 设置文字的样式
        NSMutableDictionary *textAttrs = [NSMutableDictionary dictionary];
        textAttrs[NSForegroundColorAttributeName] = HWColor(123, 123, 123);
        NSMutableDictionary *selectTextAttrs = [NSMutableDictionary dictionary];
        selectTextAttrs[NSForegroundColorAttributeName] = [UIColor orangeColor];
        [childVc.tabBarItem setTitleTextAttributes:textAttrs forState:UIControlStateNormal];
        [childVc.tabBarItem setTitleTextAttributes:selectTextAttrs forState:UIControlStateSelected];
        
        // 先给外面传进来的小控制器 包装 一个导航控制器
        HWNavigationController *nav = [[HWNavigationController alloc] initWithRootViewController:childVc];
        // 添加为子控制器
        [self addChildViewController:nav];
    }
    
    #pragma mark - HWTabBarDelegate代理方法
    - (void)tabBarDidClickPlusButton:(HWTabBar *)tabBar
    {
        UIViewController *vc = [[UIViewController alloc] init];
        vc.view.backgroundColor = [UIColor redColor];
        [self presentViewController:vc animated:YES completion:nil];
    }
    
    @end

    设置好之后,点击发微博的按钮的时候,怎么去modal出一个新窗口呢,这时候就需要用到代理了。

    注意到,我们用KVC修改tabBar之后并没有去设置代理,因为我们自定义的tabBar继承自系统自带的,我们定义delegate的时候,也需要继承自系统的,用KVC去修改之后,不用再去设置代理,因为已经设置好了。

     



沪ICP备19023445号-2号
友情链接