RootTabBarController
這個類用來設置標籤欄控制器,繼承自系統的UITabBarController。
在此先大致說下一般app的結構。一般來說結構就兩種,一種是像美團淘寶之類的,下邊是一個標籤欄控制器,劃分成4個或5個模塊。
另一種是像百度地圖 之類的,看似只有一個主界面
開發前先明確自己的結構是屬於哪種類型的,不要出現根部是ViewController,然後push到下一個界面是TabbarController。
錯亂的結構一個是邏輯不清晰,另一個是後期不同業務線界面跨越性的跳轉會變得麻煩。即使是有需求需要完成一個控制器後面是多個控制器這樣的,我們也不用tabbarController來實現,我們可以用Viewcontroller容器等其他方案來實現。本身tabbarController設計出來便是用來作爲根結構分模塊的。
在開發前我們需要明確下哪些是我們必須的業務線,哪些是業務之外的額外功能線。舉個簡單例子。比如說登錄,註冊這些功能實際上和我們的主功能是關係不大的。我們便可以剔除出來。在storyboard中便可以表示爲如下兩條開發線,使其完全隔離開來,當我們登錄時將根部控制器換爲登錄的控制器,登錄或註冊完成後需要進入主界面時則將根部控制器變爲TabbarController。後續代碼會有相應的演示。
先讓我們建一個根控制器,進入下界面。
關於底部標籤欄上的自定義,我使用的方法比較簡單,直接在原有的tabbar上覆蓋一層view,然後再在這層view上添加button,當點擊button時觸發TabbarController的方法。詳見代碼
1. 建立繼承自UITabBarController的根標籤控制器RootTabBarController,同時再生成一個同名的storyboard。
2. RootTabBarController的storyboard中拖拽一個TabBarController,類型和Storyboard ID都設置爲同名的RootTabBarController,並將其設置爲初始化控制器
3. 工程配置環境設置Main Interface爲RootTabBarController
4. 刪除原有的Main.storybard
啓動程序確保成功。
我這裏生成控制器時沒有使用xib而是生成的一個同名的storyboard。簡單的說我是將storyboard當做xib來用的。Storyboard在拖動組件展示ui,或者複製storyboard時都比xib好用。
另外雖然storyboard中可以放置完整的整個app的控制器界面,但是我仍然是一個Controller對應一個storyboard。一個是因爲開發的電腦顯示器無法同時展示過多的界面,另一個是因爲每次點擊storyboard後,即使沒有修改,git都認爲是有變動,在團隊開發時大家點入同一個storyboard中就會造成衝突。
爲了能方便的調用storyboard我們可以寫一個宏來使用,如下,這是爲什麼我要將類名和storyboard名以及storyboard中對於控制器的ID設置爲一樣的原因。
接着我們封裝一個用於標籤欄上自定義的TabBarBtn,在RootTabbarController放置TabBarbtn到標籤欄上,設置TabBarBtn點擊時觸發的事件來實現標籤欄切換的功能。因爲是一邊寫一邊改,所以寫的時候會忽略很多修改後的地方,可自行查閱項目代碼,
詳情如下:
#import "RootTabBarController.h"
#import "HomeViewController.h"
#import "MessageViewController.h"
#import "FriendViewController.h"
#import "OurViewController.h"
#import "TabBarBtn.h"
@interface RootTabBarController ()
{
NSUInteger selectIndex;
UIView *tabbarView;
}
@end
@implementation RootTabBarController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
//初始化控制器
[self initViews];
//初始化標籤欄
[self initTabbarView];
}
//初始化控制器
- (void)initViews
{
HomeViewController *homeCon = gotStoryController(@"HomeViewController");
BaseNaviController *homeNavi = [[BaseNaviController alloc]initWithRootViewController:homeCon];
MessageViewController *messageCon = gotStoryController(@"MessageViewController");
BaseNaviController *messageNavi = [[BaseNaviController alloc]initWithRootViewController:messageCon];
FriendViewController *friendCon = gotStoryController(@"FriendViewController");
BaseNaviController *friendNavi = [[BaseNaviController alloc]initWithRootViewController:friendCon];
OurViewController *ourCon = gotStoryController(@"OurViewController");
BaseNaviController *ourNavi = [[BaseNaviController alloc]initWithRootViewController:ourCon];
NSArray *navis = @[homeNavi,messageNavi,friendNavi,ourNavi];
self.viewControllers = navis;
}
/**
初始化標籤欄
- returns: void
*/
#pragma mark 初始化標籤欄
- (void)initTabbarView
{
tabbarView = [[UIView alloc]initWithFrame:self.tabBar.bounds];
tabbarView.backgroundColor = [UIColor whiteColor];
[self.tabBar addSubview:tabbarView];
self.tabBar.autoresizesSubviews = NO;
tabbarView.autoresizesSubviews = NO;
NSArray *backgroud = @[@"tb_home_n",@"tb_message_n",@"tb_bbs_n",@"tb_me_n"];
NSArray *heightBackground = @[@"tb_home_s",@"tb_message_s",@"tb_bbs_s",@"tb_me_s"];
NSArray *titles = @[@"首頁",@"消息",@"好友",@"我的"];
for (int i=0; i<backgroud.count; i++) {
NSString *backImage = backgroud[i];
NSString *heightImage = heightBackground[i];
NSString *title = titles[i];
TabBarBtn *button = [TabBarBtn buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(kScreenWidth/titles.count*i, 0, kScreenWidth/titles.count, tabbarView.height);
button.tag = i+100;
[button setTitle:title forState:UIControlStateNormal];
button.titleLabel.font = [UIFont systemFontOfSize:12];
button.titleLabel.textAlignment = NSTextAlignmentCenter;
[button setTitleColor:[UIColor darkGrayColor] forState:UIControlStateNormal];
[button setTitleColor:kColor(46, 199, 255) forState:UIControlStateDisabled];
[button setImage:[UIImage imageNamed:backImage] forState:UIControlStateNormal];
[button setImage:[UIImage imageNamed:heightImage] forState:UIControlStateDisabled];
[button addTarget:self action:@selector(selectedTab:) forControlEvents:UIControlEventTouchUpInside];
[tabbarView addSubview:button];
if (i == 0) {
button.enabled = NO;
}
}
}
#pragma mark - -------------------------Actions-------------------
#pragma mark tabBar按鈕點擊事件
/**
* tabBar按鈕點擊事件
*
* @param button tabBar按鈕
*/
- (void)selectedTab:(UIButton *)button {
self.selectedIndex = button.tag-100;
}
/**
* 選擇不同的tabBar按鈕後修改不同的按鈕狀態
*
* @param selectedIndex tabbarController的值
*/
- (void)setSelectedIndex:(NSUInteger)selectedIndex
{
[super setSelectedIndex:selectedIndex];
for (int i = 100; i<105; i++) {
UIButton *btn = (UIButton *)[tabbarView viewWithTag:i];
btn.enabled = YES;
}
UIButton *btn = (UIButton *)[tabbarView viewWithTag:selectedIndex+100];
btn.enabled = NO;
//每次點擊後都需要將自己的tabbarview放置在最頂層,放置系統的tabbarItem覆蓋
[self.tabBar insertSubview:tabbarView atIndex:self.tabBar.subviews.count-1];
}
//系統自動調用默認方法隱藏掉tabbar上面的字體
+ (void)initialize
{
// 通過appearance統一設置所有UITabBarItem的文字屬性
// 後面帶有UI_APPEARANCE_SELECTOR的方法, 都可以通過appearance對象來統一設置
NSMutableDictionary *attrs = [NSMutableDictionary dictionary];
attrs[NSFontAttributeName] = [UIFont systemFontOfSize:0];
attrs[NSForegroundColorAttributeName] = [UIColor clearColor];
NSMutableDictionary *selectedAttrs = [NSMutableDictionary dictionary];
attrs[NSFontAttributeName] = [UIFont systemFontOfSize:0];
attrs[NSForegroundColorAttributeName] = [UIColor clearColor];
UITabBarItem *item = [UITabBarItem appearance];
[item setTitleTextAttributes:attrs forState:UIControlStateNormal];
[item setTitleTextAttributes:selectedAttrs forState:UIControlStateSelected];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}