UITabBarControler

管理多個控制器,以不可變數(shù)組管理,而且創(chuàng)建時必須要全部指定所管理的多個視圖控制器,而且多個視圖控制器同時存在,沒有層次關(guān)系的視圖控制器(同時存在,互不干擾)空間不回收

QQ.png

子控制器

QQ.png

結(jié)構(gòu)

UITransitionView---存放當(dāng)前子控制器的view
UITabBar---導(dǎo)航條(在下方)高度為49;添加了幾個子控制器,底下的TabBar會被平分;能夠被點擊,切換到對應(yīng)的view。
UITabBar上最多可以顯示5個Tab,當(dāng)我們往UITabBarController中添加超過的viewController超過5個時候,最后一個一個就會自動變成省略號。

基本使用

Info.plist 去掉main
添加視圖:UIWindow—>UITabBarcontroller—>UINavigationController— >UIViewController,必須按此順序添加


QQ.png

注意:以上標(biāo)題不這樣設(shè)

添加多個子控制器


QQ.png

PS:可以有導(dǎo)航控制器,即TabBarControler也可以控制導(dǎo)航控制器
PS:TabBarControler默認(rèn)顯示第一個子控制器的view,但是可以改

tabVC.selectedIndex = 1  ;  

其中所賦的置是子控制器的索引,從0開始為第一個。

管理原則

  • UITabBarController會一次性初始化所有子控制器,但是默認(rèn)只加載第一個控制器視圖,其他視圖控制器只初始化,默認(rèn)不會加載。只有當(dāng)需要顯示的時候才loadView加載。
  • 子控制器加載后會存在內(nèi)存中,下次直接顯示,切換子控制器不會銷毀之前顯示的子控制器。只是所顯示的view會先從屏幕移除,再添加。
  • 每個視圖控制器都有一個tabBarController屬性,通過它可以訪問所在的TabBarController,而且對于TabBarController的直接子視圖,其tabBarController等于parentViewController。
  • 每個視圖控制器都有一個tabBarItem屬性,通過它控制視圖在UITabBarController的tabBar中的顯示信息。


    QQ.png

設(shè)置TabBar內(nèi)容

QQ.png

UITabBarButton
要顯示什么內(nèi)容,由對應(yīng)的子控制器的tabBarItem屬性決定。


QQ.png

如:


QQ.png

UITabBar有一些方法是可以改變自身狀態(tài),但是對于UITabBarController自帶的tabBar,不能直接去修改其狀態(tài),否則將會拋出異常

切換選中的子控制器

1.通過selectedIndex屬性可以獲得當(dāng)前選中的viewController。設(shè)置該屬性,可以顯示viewControllers中對應(yīng)index的viewController。
2.通過selectedViewController屬性可以獲取到當(dāng)前顯示的viewController。所以,通過設(shè)置該屬性可以設(shè)置當(dāng)前選中的viewController,同時更新selectedIndex。

主流框架

以TabBarControler作為根控制器,控制多個導(dǎo)航控制器及其view


QQ.png

首先在storybord中刪除默認(rèn)的viewcontroler,拖一個tabBarControler,設(shè)為默認(rèn)控制器

Modal切換方式(從底部向上出現(xiàn),直到覆蓋這個view)

QQ.png

presentViewControler:方法
第一個參數(shù)為即將要出現(xiàn)的控制器,第二個參數(shù)可以設(shè)置動畫效果,第三個參數(shù)表示,當(dāng)modal完成時做什么事(可以為nil)。


QQ.png

PS:當(dāng)modal時,先移除當(dāng)前的view,然后把即將出現(xiàn)的view添加到窗口。
dismissViewControler:方法
一般用當(dāng)前控制器調(diào)用此方法,讓自己關(guān)閉掉

自定義TabBar

新建一個類,繼承自UIView。
在.h中聲明模型,保存TabBar子控件的內(nèi)容(圖片,文字)

@property(nonatomic ,strong) NSArray *items;   //模型

在模型的set方法中添加子控件(一般是button),并設(shè)置子控件的內(nèi)容

-(void)setItems:(NSArray *)items{
    _items = items;

    for(int i = 0;i < self.items.count ; i++){
        //添加子控件
        UIButton *btn = [[UIButton alloc] init];
        [self addSubview:btn];
        
        //設(shè)置子控件btn的內(nèi)容
        UITabBarItem *tbItem = self.items[i];
        [btn setImage:tbItem.image forState:UIControlStateNormal];
        [btn setImage:tbItem.selectedImage forState:UIControlStateSelected];
//        [btn setBackgroundImage:tbItem.image forState:UIControlStateNormal];    設(shè)為背景圖片,能夠占滿btn、
//        [btn setBackgroundImage:tbItem.selectedImage forState:UIControlStateSelected];
        
        //監(jiān)聽子控件btn,當(dāng)按下就選中
        [btn addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchDown];   
    }
}

在layoutSubViews方法中布局子控件

-(void)layoutSubviews{
    [super layoutSubviews];
    
    CGFloat btnX = 0;
    CGFloat btnY = 0;
    CGFloat btnW = self.frame.size.width / self.subviews.count;
    CGFloat btnH = self.frame.size.height;
    
    int i = 0;
    for(UIButton *btn in self.subviews){
        btn.tag = i;
        btnX = i * btnW;
        btn.frame = CGRectMake(btnX, btnY, btnW, btnH);
        
        if(i ==0 )
            [self btnClick:btn];   //默認(rèn)初始時,選中第一個按鈕
        i++;
    }
}

實現(xiàn)控制器的切換
原理:自身不能做切換,只有控制器才能切換-->通過代理,通知外面的控制器(TabBarVC),切換子控制器-->利用selectedIndex屬性實現(xiàn)切換-->由監(jiān)聽子控件(button)的點擊,其tag與selectedIndex相對應(yīng)。
設(shè)置代理:在.h中聲明

//設(shè)置代理
@class PDTabBar;
@protocol PDTabBarDelegate <NSObject>
-(void)tabBar:(PDTabBar *)tabBar index:(NSInteger)index;  //代理方法

@end

@interface PDTabBar : UIView
@property(nonatomic,weak) id<PDTabBarDelegate> delegate;   //聲明代理

@end

PS:代理方法在TabBar控制器中具體實現(xiàn)

-(void)tabBar:(PDTabBar *)tabBar index:(NSInteger)index{
    self.selectedIndex = index;    //傳遞了tag,作為index,實現(xiàn)切換
}

PS:必須遵守它的協(xié)議<PDTabBarDelegate>,并將自己設(shè)為它的代理對象
子控件button的監(jiān)聽方法

-(void)btnClick:(UIButton *)btn{
    //3步曲( 先聲明一個 選中按鈕 屬性 )
    self.selectedBtn.selected = NO;   //取消上次選中
    btn.selected = YES;    //選中當(dāng)前點擊的按鈕
    self.selectedBtn = btn;    //記錄之
    
    //調(diào)用代理方法,通知外面切換子控制器
    if([self.delegate respondsToSelector:@selector(tabBar:index:)]){
        [self.delegate tabBar:self index:btn.tag];    //調(diào)用代理方法,把tag作為參數(shù)傳遞出去
    }
}

至此,自定義TabBar完成,外界(在TabBarController中)基本使用如下:
使用自定義TabBar
兩種選擇:一是移除系統(tǒng)的TabBar,二是只移除系統(tǒng)TabBar的子控件
1.移除系統(tǒng)TabBar(缺點:失去系統(tǒng)自帶的滑動返回功能)

    [self.tabBar removeFromSuperview];    //先移除

    PDTabBar *newTabBar = [[PDTabBar alloc] init];    //創(chuàng)建自定義TabBar
    newTabBar.items = self.items;    //把外界數(shù)據(jù)模型 傳遞到 自定義TabBar的模型數(shù)組里。(此時調(diào)用了items的set方法(同時添加了子控件)
    [self.view addSubview:newTabBar];   //添加到控制器的view上

    newTabBar.frame = self.tabBar.frame;   //布局 ( 此時 self.tabBar還沒有被銷毀 )
    newTabBar.backgroundColor = [UIColor blackColor];

數(shù)據(jù):在設(shè)置TabBar內(nèi)容時,把TabBar子控件的內(nèi)容傳遞到模型

    VC.tabBarItem.image = image;
    VC.tabBarItem.selectedImage = selectImg;
    VC.tabBarItem.title = title;
    [self.items addObject:VC.tabBarItem];   

隱藏底部TabBar

2.只移除系統(tǒng)TabBar的子控件(仍有滑動返回功能)
創(chuàng)建并添加

    PDTabBar *newTabBar = [[PDTabBar alloc] init];   //創(chuàng)建自定義TabBar
    newTabBar.items = self.items;
    [self.tabBar addSubview:newTabBar];   //添加到系統(tǒng)TabBar上面,此時自定義的TabBar作為系統(tǒng)TabBar的一個子控件
    
    newTabBar.frame = self.tabBar.bounds;   //布局,要用bounds,不能用frame
    newTabBar.backgroundColor = [UIColor blackColor];

移除系統(tǒng)TabBar的子控件
要在viewWillAppear方法中移除系統(tǒng)的TabBar的子控件UITabBarButton(私有),因為在viewDidLoad中子控件還沒有加載完

-(void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];
    //遍歷TabBar的子控件
    for(UIView *view in self.tabBar.subviews){
        if(![view isKindOfClass:[PDTabBar class]])
                [view removeFromSuperview];
    }
}

執(zhí)行以上操作后,系統(tǒng)TabBar中 只有自定義的TabBar

隱藏底部TabBar
在storybord中設(shè)置將要顯示的控制器(非根控制器)的Hide Bottom Bar on Push(勾選)
或者采用代碼方法,在所要跳轉(zhuǎn)的控制器中:

-(void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];
    self.tabBarController.tabBar.hidden = YES;   //切換后,隱藏底部TabBar
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容