當我們想要做一個界面類似 聯系人 那樣的程序時,就一定會用到 UITabBar,它可以幫我們添加、管理許多的Tab項, 使我們的程序包含不同的操作模式,由於管理UITabBar可能會有些麻煩,所以apple也幫我們對其進行了封裝,產生了簡單好用的UITabBarController,就像UITableViewController對UITableView的封裝,只不過在用到UITabBarController時,我們不用像使用UITableViewController那樣去繼承它。
一、UITabBarController主要用來管理你提供的content view controllers,而每一個 content view controller則負責管理自己的view層級關系,通常,當你的程序想要提供一些平行(同一個等級的)的不同界面,而恰好這些界面使用到的數據是一類的,或者功能是一個系列的,那 tab bar interface 是非常有用的. 在這樣的 tab bar interface界面中,你可以設置許多的 tab ,每一個 tab則一定要指定一個content view controller,當某個tab被點擊時,UITabBarController就會選中該tab並且顯示該viewController所持有的content view.在apple官網上有一張關於UITabBarController的圖片,如下:
觀察上圖,最下面的那個Tab bar,這是由UITabBarController自己負責維護的,就像UINavigation Bar是由UINavigationController負責維護一樣,不建議被修改,但如果實在需要改變的話,只能通過UITabBarController提供的方法去修改。
你有沒有發現,絕大多數的iOS程序,如果他用到了UITabBarController,那么他的外觀就像上圖,Tab bar默認在下面,但有時我們又希望將他顯示到最上面去,就像android的聯系人程序一樣,其實只要幾句代碼就行了:
CGRect frame = CGRectMake(0, 20, 320, 44) tabBarController.tabBar.frame = frame;
呵呵,這樣不就可以了,你想放哪放哪,不過可別太難看了。
二、一個標准的 tab bar interface 通常由下列對象組成:
1.一個 UITabBarController 對象
2.每一個tab 都必須有一個content view controller(所以UITabBarController有一個屬性是viewControllers)
3.一個可選的delegate對象
注意了:通常而言,UITabBarController一般作為應用程序的rootViewController,而且它不能作為UINavigationController的rootViewController.
所以初始化的代碼一般這樣寫:
self.viewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil]; ViewControllerA *A = [[ViewControllerA alloc]initWithNibName:@"ViewControllerA" bundle:nil]; ViewControllerB *B = [[ViewControllerB alloc]initWithNibName:@"ViewControllerB" bundle:nil]; ViewControllerC *C = [[ViewControllerC alloc]initWithNibName:@"ViewControllerC" bundle:nil]; ViewControllerD *D = [[ViewControllerD alloc]initWithNibName:@"ViewControllerD" bundle:nil]; ViewControllerE *E = [[ViewControllerE alloc]initWithNibName:@"ViewControllerE" bundle:nil]; UITabBarController *tabBarController = [[UITabBarController alloc]init]; A.tabBarItem = [[UITabBarItem alloc]initWithTabBarSystemItem:UITabBarSystemItemBookmarks tag:0]; self.viewController.tabBarItem = [[UITabBarItem alloc]initWithTabBarSystemItem:UITabBarSystemItemContacts tag:1]; B.tabBarItem = [[UITabBarItem alloc]initWithTabBarSystemItem:UITabBarSystemItemDownloads tag:2]; C.tabBarItem = [[UITabBarItem alloc]initWithTabBarSystemItem:UITabBarSystemItemHistory tag:3]; D.tabBarItem = [[UITabBarItem alloc]initWithTabBarSystemItem:UITabBarSystemItemSearch tag:4]; E.tabBarItem = [[UITabBarItem alloc]initWithTabBarSystemItem:UITabBarSystemItemTopRated tag:5]; tabBarController.viewControllers = @[self.viewController,A,B,C,D,E]; tabBarController.customizableViewControllers = @[B,C,D,E]; [tabBarController setSelectedIndex:2]; tabBarController.delegate = self; // CGRect frame = CGRectMake(0, 20, 320, 44); // tabBarController.tabBar.frame = frame; self.window.rootViewController = tabBarController;
你應該像上面那樣,為每一個viewController指定一個tabBarItem,當然你也可以這樣初始化
A.tabBarItem = [[UITabBarItem alloc]initWithTitle:<#(NSString *)#> image:<#(UIImage *)#> tag:<#(NSInteger)#>];
從而達到自定義tab bar item外觀的目的,而不必使用系統提供好的,但此時你使用的圖片大小要有規定了,一般ipad在60*60,iPhone在30*30左右,
再來看下面這張圖,它描繪了UITabBarController和它的屬性viewControllers、customizableViewControllers和selectedViewController等的關系
如果你的viewControllers屬性添加了多於五個的items,那tab bar controller將會自動插入一個特殊的view controller,稱為 More view controller,該 controller 將會負責管理多於的items,這個More view controller提供一個自定義的界面,用table的方式呈現多余的view controller,並且view controller的數量是不限制的。對於這個more view controller ,UITabBarController 通過一個屬性----moreNavigationController持有它的引用,但看名字就知道他是一個UINavigationController對象,所有我們可以修改它的一些屬性,如:
UINavigationController *nav = tabBarController.moreNavigationController;
[nav setNavigationBarHidden:YES];
當然,如不是必須,最好不要修改它。
三、在創建一個tab bar interface之前,你應該考慮清楚程序是否真的需要使用該布局,而且應該在正確的地方使用它……通常通過下面這些方式使用:
1.作為window的root view controller
2.作為 split view interface(iPad專有界面,不知道的可以百度下)中的其中一個一個view controller
3.作為modal view使用
4.作為UIPopoverController(iPad專有)的content view
四、在tab bar interface創建好后,我們可以用代碼動態的修改它,如:增加或刪除tab項,對於這種操作,通常我們需要重新指派UITabBarController的viewConrollers屬性來進行,有人可能要問了,為什么要重新指派,viewController不是一個數組嗎,不能直接通過數組的remove方法直接刪除嗎,可別忘了,這個屬性的類型是個NSArray,不能進行刪除,添加的。我們知道,當tab bar interface界面顯示后,我們只能在某一時刻操作一個界面,因此,修改viewControllers屬性必須在某個content viewController中完成,我們可以通過UIViewController的屬性 tabBarController來獲得UITabBarController的引用,就像獲得UINavigationController的引用一樣,修改代碼如下:

NSMutableArray* newArray = [NSMutableArray arrayWithArray:self.tabBarController.viewControllers];
[newArray removeObject:self];
[self.tabBarController setViewControllers:newArray animated:YES];
五、當你點擊某個tab項時,它對應的content viewController會得到顯示,
但有時也許我們就是不希望某個被你點擊的view得到顯示,如:某個viewController所需的數據還沒有完成加載,或者必須等某個登陸界面 完成登陸后
才能激活其他viewController,此時你可以實現UITabBarControllerDelgate中的方法
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController NS_AVAILABLE_IOS(3_0)
通過設置返回值來禁止某個viewController能否被選中,如下:

- (BOOL)tabBarController:(UITabBarController *)aTabBar shouldSelectViewController:(UIViewController *)viewController { if (![self hasValidLogin] && (viewController != [aTabBar.viewControllers objectAtIndex:0]) ) { // Disable all but the first tab. return NO; } return YES; }
當然你也可以通過代碼手動去選擇某個viewController,只要設置UITabBarController的屬性selectedViewController 或者 selectedIndex(從0開始),但此時代理的方法是無效的,也就是說,如果你通過代碼來選中某個viewController的話,則肯定是可以選中的。。。
六、其實UITabBarController還允許你對viewControllers進行排序,你可以使任意一個viewController出現在第一個tab項中,上面我們有提到moreNavigationController,當tabs超過5個時,也就是viewControllers的個數超過5個時,最后一個的tab item默認為more,然后那些沒能顯示在tab上的viewController便可通過moreNavigationController以列表的形勢顯示,那是不是那些沒能在tab上顯示的viewController就永遠只能在moreNavigationController的列表中顯示了??當然不是,當我么點擊more tab時會出現下面左圖的界面,然后再點擊navigationBar左邊的編輯按鈕時會出現下面的右圖,此時你可以把這些顯示的tab直接拉到下面的 tab bar中,從而達到自定義tab的功能
那如果我希望某個viewController一直在tab上顯示,二不希望用戶將其排列到more tab中去,那該怎么辦呢。。。。UITabBarController有個屬性customizableViewControllers
由它來決定哪些viewController允許重排列。。不過這里要注意了,默認情況下customizableViewControllers 和 viewControllers屬性包含的內容是一樣的,你可以手動設置它為viewControllers的字集(只能是字集),但當你重新更新了viewControllers時,customizableViewControllers又會默認和viewControllers相等,希望表達清楚了。。。
七、
看看上面的圖,是不是和應用程序的badge很像,當某個tab有信息需要你處理時,顯示這個能很好的引起用戶的注意,而你只需這樣做
if (numberOfNewItems == 0) self.tabBarItem.badgeValue = nil; else self.tabBarItem.badgeValue = [NSString stringWithFormat:@"%d", numberOfNewItems];
self 是 viewContrller ,不過要注意了,這里的badgeValue是個NSString類型的,不要和下面的弄混了
[UIApplication sharedApplication].applicationIconBadgeNumber = 2
通常情況下,當我們點擊顯示了badge的那個tab后,這個紅色的提示就應該消失。呵呵,可別忘了,當你切換tab時,viewController的聲明周期可是一樣的,它會執行那些
viewDidAppear 、viewDidDisappear等方法,所以最好的辦法就是在該viewContrller的
-(void)viewDidAppear:(BOOL)animated方法中,將其重置為空,
如:self.tabBarItem.badgeValue = nil;
八、UITabBarController是否能旋轉呢?那要看它的那些viewControllers了,如果在viewControllers中只要有一個viewController不支持某個方向的旋轉,那UITabBarControlelr就也不能旋轉到該方向。再來看看它的一些代理方法,我就簡單描述下:
//當你選中某個tab 項時調用,我們可以在這里做一些操作,如隱藏狀態欄,導航欄什么的。
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
//當點擊more后出現moreNavigationController畫面時,點擊那個edit按鈕時觸發
- (void)tabBarController:(UITabBarController *)tabBarController willBeginCustomizingViewControllers:(NSArray *)viewControllers NS_AVAILABLE_IOS(3_0)
//下面兩個方法在點擊那個done按鈕時觸發
- (void)tabBarController:(UITabBarController *)tabBarController willEndCustomizingViewControllers:(NSArray *)viewControllers changed:(BOOL)changed NS_AVAILABLE_IOS(3_0)
- (void)tabBarController:(UITabBarController *)tabBarController didEndCustomizingViewControllers:(NSArray *)viewControllers changed:(BOOL)changed