控制器:UITabBarController

本文详细介绍了如何使用Objective-C操作UITabBarController,包括初始化、添加子控制器、自定义UITabBar及UITabBarButton的方法,同时提供了Swift和OC两种语言的实现方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、UITabBarController的使用步骤
初始化UITabBarController
设置UIWindow的rootViewController为UITabBarController
根据具体情况,通过addChildViewController方法添加对应个数的子控制器

2、UITabBarController的子控制器

UITabBarController添加控制器的方式有2种
添加单个子控制器
- (void)addChildViewController:(UIViewController *)childController;

设置子控制器数组
@property(nonatomic,copy) NSArray *viewControllers;

3、UITabBar
如果UITabBarController有N个子控制器,那么UITabBar内部就会有N个UITabBarButton作为子控件

如果UITabBarController有4个子控制器,那么UITabBar的结构大致如下图所示
这里写图片描述

4、UITabBarButton
这里写图片描述

二、UITabBarController
如果系统的 UITabBarButton 不能满足我们的开发 , 比如 下列这种效果:
这里写图片描述

有两种三种方法去实现它:

第一种: 在我们 给TabBarController 添加子控制器的时间 ,在 第三的位置 加入一个 UIViewController ,需要放button的位置 撑开 ,然后定义一个 属性button,

@property  (nonatomic , weak)   UIButton *centerButton ;

- (void)customBtn{

    if ( _centerButton == nil) {
        _centerButton = [[UIButton alloc]init];
    }

    //长度
    CGFloat w = self.tabBar.bounds.size.width / self.childViewControllers.count;
    CGRect rect = CGRectMake(0, 0, w, self.tabBar.bounds.size.height);

    //设置frmae
    _centerButton.frame = CGRectOffset(rect, 2 * w, 0);
    [_centerButton setImage:[UIImage imageNamed:@"tabbar_compose_icon_add"] forState:UIControlStateNormal];
     [_centerButton setImage:[UIImage imageNamed:@"tabbar_compose_icon_add_highlighted"] forState:UIControlStateHighlighted];

    //设置背景图片
    [_centerButton setBackgroundImage:[UIImage imageNamed:@"tabbar_compose_button"] forState:UIControlStateNormal];
     [_centerButton setBackgroundImage:[UIImage imageNamed:@"tabbar_compose_button_highlighted"] forState:UIControlStateHighlighted];

    //设置一个监听事件
    [_centerButton addTarget:self action:@selector(clickAdd) forControlEvents:UIControlEventTouchUpInside];

    [self.tabBar addSubview:_centerButton];
}

注意 custom的调用位置 :
1、- (void)viewDidLayoutSubviews

2、- (void)viewWillAppear:(BOOL)animated

第二种方式

第二种方法: 
1、自定义 整个 TabBar  ,利用  layoutSubviews 这个  方法去设置每一个button的 frame ,把原来  view的 self.tabBar 移除 ,替换成我们定义的tabBar 

2、在创建控制器的时间 把自定义那个 button添加到TabBar上,在根据按钮的不同的tag值去实现 代理,点击切换不同控制器
- (void)addTabBarButton:(UITabBarItem *)item
{
    //创建按
    TSZTabBarButton *button = [TSZTabBarButton buttonWithType:UIButtonTypeCustom];
    //添加
    [self addSubview:button];
    //设置图片
    [button setBackgroundImage:item.image forState:UIControlStateNormal];

    [button setBackgroundImage:item.selectedImage forState:UIControlStateSelected];

    //点击添加单击时间
    [button addTarget:self action:@selector(clickButton:) forControlEvents:UIControlEventTouchDown];
    //默认选中第0个按钮
    NSInteger count = self.subviews.count;
    if( 1 == count)
    {
        [self clickButton:button];
    }
}

//给我们创建出来的加frame
 - (void)layoutSubviews
{
    NSInteger count = self.subviews.count;

    CGFloat btnW = self.frame.size.width/5;
    CGFloat btnH = self.frame.size.height;

    //循环创建
    for(int i =0 ; i< count;i++)
    {
        //取出创建的按钮
        UIButton *btn = self.subviews[i];

        CGFloat btnY = 0;
        CGFloat btnX = btnW * i;

        //设置frame
        btn.frame = CGRectMake(btnX, btnY,btnW , btnH);

        //设置按钮的tag
        btn.tag = i;
    }
}

#pragma mark --- 点击事件的实现
//点击事件的实现
- (void)clickButton:(UIButton *)btn
{
    //通知代理,使用懒加载的方式
    if([self.delegate respondsToSelector:@selector(tabBar:didselectedButtonFrom:to:)])
    {
        [self.delegate tabBar:self didselectedButtonFrom:self.currentSelectedBtn.tag to:btn.tag];
    }

    //取消上一次选中
    self.currentSelectedBtn.selected = NO;

    //设置按钮为选中
    btn.selected = YES;
    //记当前选中
    self.currentSelectedBtn = btn;
}

第三种

第三种方法:自定义 TabBar , 但是只是 创建一个需要的button , 在layoutSubviews  布局子控件必须这样写 , 的时候进行判断
 //判断 UITabBarButton是TabBar上 的 按钮
        Class class = NSClassFromString(@"UITabBarButton");
        if ([child isKindOfClass:class]) {
            //设置宽度
            child.width = tabW;

            //设置x 的坐标
            child.x = tabIndex * tabW ;
            //增加索引
            tabIndex++;
            //中间的发送按钮不是UITabBarButton  是我们自定义的
            if (tabIndex  == 2){
                tabIndex++;
            }
        }
如果是 它的子控件就是 tanBarItem 按照 计算设置frame ,先固定放置的按钮。

把创建好的button放上去就好了 , 只需要给这个一个按钮设置一个代理就可以完成界面的切换
//布局子控件
- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        //设置所需要的button
        [self setupBtn];
    }
    return self;
}

- (instancetype)initWithCoder:(NSCoder *)coder
{
    self = [super initWithCoder:coder];
    if (self) {
         //设置所需要的button
        [self setupBtn];
    }
    return self;
}

#pragma mark: 实现所需要的button
- (void)setupBtn{
    //添加一个按钮到tabBar上
    UIButton *btn = [[UIButton alloc]init];

    //设置背景颜色
    [btn setBackgroundImage:[UIImage imageNamed:@"tabbar_compose_button"] forState:UIControlStateNormal];
     [btn setBackgroundImage:[UIImage imageNamed:@"tabbar_compose_button_highlighted"] forState:UIControlStateHighlighted];
    [btn setImage:[UIImage imageNamed:@"tabbar_compose_icon_add"] forState:UIControlStateNormal];
    [btn setImage:[UIImage imageNamed:@"tabbar_compose_icon_add_highlighted"] forState:UIControlStateHighlighted];

    //设置frame ,按钮的大小和背景图片的大小一致

    btn.size = btn.currentBackgroundImage.size;

    [self addSubview:btn];

    //使用它
    self.plusBtn = btn ;
}

#pragma mark:layoutSubviews  布局子控件必须这样写

- (void)layoutSubviews{
    [super layoutSubviews];

    //循环添加按钮
    //1、设置发送按钮的位置
    self.plusBtn.centerX = self.width * 0.5;

    self.plusBtn.centerY = self.height * 0.5;
    //设置其他位置的尺寸
    CGFloat tabW = self.width  / 5 ;

    //当前tab的索引
    CGFloat tabIndex = 0;

    for (UIView *child  in  self.subviews) {
        //判断 UITabBarButton是TabBar上 的 按钮
        Class class = NSClassFromString(@"UITabBarButton");
        if ([child isKindOfClass:class]) {
            //设置宽度
            child.width = tabW;

            //设置x 的坐标
            child.x = tabIndex * tabW ;
            //增加索引
            tabIndex++;
            //中间的发送按钮不是UITabBarButton  是我们自定义的
            if (tabIndex  == 2){
                tabIndex++;
            }
        }
    }
}

三 、实现 这一种效果
这里写图片描述

1、swift的实现

1、 必须是自定义整个tabBar ,使用  核心动画 做个一个背景 ,在把白色的背景添加到 tabBar上,在layoutSubviews 上去设置所有 子控件的  frame ,在点击的时间实现 背景的动画效果

下面是swift的这个效果 


/// 定义一个代理
protocol TSZTabBarDelegate: NSObjectProtocol {
    func tabBar(tabBar:TSZTabBar , toIndex: Int)
}

class TSZTabBar: UIView {

    //定义全局属性
     var currentBtnSelect: UIButton?
    var backImage:UIImageView?
    weak var delegate: TSZTabBarDelegate?
    /**
    通过代码添加按钮
    */
    override init(frame: CGRect) {
        super.init(frame: frame)
        self.addBackGround()
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }


    //MARK  - 添加按钮
    func  addButtonWithBarItem(tabItem:UITabBarItem){
        //创建按钮
        let btn = UIButton()
        //添加到view
        self.addSubview(btn)
        //设置图片
        btn.setImage(tabItem.image, forState: UIControlState.Normal)
        btn.setImage(tabItem.selectedImage, forState: UIControlState.Selected)
        //添加监听事件
        btn.addTarget(self, action: "btnCilck:", forControlEvents: UIControlEvents.TouchDown)

        //默认设置选中第0个按钮
        let count:Int = self.subviews.count
        if 1 == count{
            btnCilck(btn)
        }
    }

    func btnCilck(btn: UIButton){
        //设置按钮的选中状态
        currentBtnSelect?.selected = false
        btn.selected = true
        //赋值
        currentBtnSelect = btn
        //改变背景颜色
        UIView.animateWithDuration(0.5) { () -> Void in
//            backImage.x = btn.x
            backImage?.frame.origin.x = btn.frame.origin.x
        }

        //启动代理
        delegate?.tabBar(self, toIndex: btn.tag)

    }

    /**
    *布局子控件
    */
    override func layoutSubviews() {
        super.layoutSubviews()
        let count = self.subviews.count - 1
        let tabBarW = self.bounds.size.width
        let tabBarH = self.bounds.size.height

        //设置背景色图片的frame
        backImage?.frame = CGRectMake(0, 5, tabBarW / CGFloat(count), tabBarH)
        //btn的大小
        let btnY:CGFloat = 0
        let btnW = tabBarW / CGFloat(count)
        let btnH = tabBarH

        for i in 1...count{
            //取出对应的button
            let btn: UIView = self.subviews[i]

            //计算frame
            let btnX: CGFloat = CGFloat(i - 1)*btnW
            //设置frame
            btn.frame = CGRectMake(btnX, btnY, btnW, btnH)
            btn.tag = i-1
        }

    }

    //添加背景图片
    func addBackGround(){

        let backGround: UIImageView = UIImageView()
        backGround.image = UIImage(named: "toolBar_shade")
        backImage = backGround
        self.addSubview(backImage!)
    }

//画图
    override func drawRect(rect: CGRect) {
        let image: UIImage = UIImage(named: "tabBar_back")!
        image .drawInRect(rect)
    }
}

2、OC的实现

#pragma - mark 通过代码添加background
- (instancetype)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame]) {
        [self addBackground];
    }
    return self;
}

#pragma - mark 添加按钮
- (void)addButtonWithtabBarItem:(UITabBarItem *)tabItem
{
    // 创建按钮
    HMTabBarButton * btn = [[HMTabBarButton alloc] init];
    [self addSubview:btn];
    // 设置图片
    [btn setImage:tabItem.image forState:UIControlStateNormal];
    [btn setImage:tabItem.selectedImage forState:UIControlStateSelected];
    
    // 监听点击事件
    [btn addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchDown];
    // 设置默认选中第0个按钮
    NSInteger count = self.subviews.count;
    if(2 == count)
    {
        [self btnClick:btn];
    }
}

#pragma - mark 添加按钮背景图片
- (void)addBackground
{
    // 添加白色图片
    UIImageView *backGroundImage = [[UIImageView alloc] init];
    backGroundImage.image = [UIImage imageNamed:@"toolBar_shade"];
    self.backGroundImage = backGroundImage;
    [self addSubview:backGroundImage];
}

#pragma  - mark 选中按钮
- (void)btnClick:(HMTabBarButton *)btn
{
    // 设置按钮的选中状态
    self.currentSelBtn.selected = NO;
    btn.selected = YES;
    self.currentSelBtn = btn;
    
    // 改变backGroundImage的frame
    [UIView animateWithDuration:0.3 animations:^{
        self.backGroundImage.x = btn.x;
    }];
    
    // 通知控制器切换子控制器
    if ([self.delegate respondsToSelector:@selector(tabBar:toIndex:)]) {
        [self.delegate tabBar:self toIndex:(int)btn.tag];
    }
    
}
#pragma  - mark 布局子控件
- (void)layoutSubviews
{
    NSInteger count = self.subviews.count - 1;
    CGFloat tabBarW = self.bounds.size.width;
    CGFloat tabBarH = self.bounds.size.height;
    
    // 设置backGroundImage的frame
    self.backGroundImage.frame = CGRectMake(0, 5, tabBarW / count, tabBarH);
    
    
    CGFloat btnY = 0;
    CGFloat btnW = tabBarW / count;
    CGFloat btnH = tabBarH;
    for (int i = 1; i <= count; i++) {
        // 取出对应的按钮
        HMTabBarButton * btn = self.subviews[i];
        // 计算frame
        CGFloat btnX = (i - 1)* btnW;
        // 设置frame
        btn.frame = CGRectMake(btnX, btnY, btnW, btnH);
        // 设置按钮tag
        btn.tag = i - 1;
    }
}

#pragma  - mark 画出大背景图片
- (void)drawRect:(CGRect)rect
{
    UIImage * image = [UIImage imageNamed:@"tabBar_back"];
    [image drawInRect:rect];
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值