標籤:ios
最近我所在的項目組對項目進行了一些基礎組件的最佳化,其中有關於UITabBarController隱藏tabBar的問題感覺有必要總結下。
一,需求分析
先來說說項目基本需求:整個項目由左側欄和主視圖組成,主視圖主體是一個UITabBarController,下屬幾個嵌套了UINavigationController的UIViewController。
要求:當在頁面上下滑動的時候,根據使用者手勢需要隱藏顯示底部欄,也就是預設的UITabBarController的tabBar。
我在設計的時候是將左側欄和主視圖通過addChildViewController的方式添加到一個容器UIViewController中,並使用了UITabBarController內建的tabBar。隱藏顯示tabBar是通過修改tabBar的frame來實現的。介面布局示範代碼如下:對CoreAnimation不夠清楚的可以看CALayer和CATransaction的詳細教程
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease]; UIViewController *parentController = [[UIViewController alloc] init]; SideBarViewController *sideBarViewController = [[SideBarViewController alloc] init];//左側欄 - 也是需要有彈出UIViewController的功能。 UINavigationController *sideBarNavController = [[UINavigationController alloc] initWithRootViewController: sideBarViewController]; sideBarNavController.navigationBarHidden = YES; [parentController addChildViewController:sideBarNavController];//添加左側欄 [parentController.view addSubview:sideBarNavController.view]; MyUITabBarController *tabBarController = [[MyUITabBarController alloc] init];//主體視圖 //[parentController addChildViewController: tabBarController];//添加這句話,介面有問題 [parentController.view addSubview: tabBarController.view]; self.window.rootViewController = parentController;
| 1234567891011 |
self.window= [[[UIWindowalloc]initWithFrame:[[UIScreenmainScreen]applicationFrame]]autorelease]; UIViewController *parentController= [[UIViewControlleralloc]init]; SideBarViewController *sideBarViewController= [[SideBarViewControlleralloc]init];//左側欄 - 也是需要有彈出UIViewController的功能。 UINavigationController *sideBarNavController= [[UINavigationControlleralloc]initWithRootViewController:sideBarViewController]; sideBarNavController.navigationBarHidden= YES; [parentController addChildViewController:sideBarNavController];//添加左側欄 [parentController.viewaddSubview:sideBarNavController.view]; MyUITabBarController *tabBarController= [[MyUITabBarControlleralloc]init];//主體視圖 //[parentController addChildViewController: tabBarController];//添加這句話,介面有問題 [parentController.viewaddSubview:tabBarController.view]; self.window.rootViewController= parentController; |
其中MyUITabBarController中的示範代碼如下:
| 123456789101112131415 |
UIViewController *controller1= [[UIViewControlleralloc]init]; UINavigationController *navigationController1= [[UINavigationControlleralloc]initWithRootViewController:controller1]; UIViewController *controller2= [[UIViewControlleralloc]init]; UINavigationController *navigationController2= [[UINavigationControlleralloc]initWithRootViewController:controller2]; navigationController1.navigationBarHidden= YES; navigationController2.navigationBarHidden= YES; //controller1.hidesBottomBarWhenPushed = YES; //controller2.hidesBottomBarWhenPushed = YES; NSArray *controllers= [NSArrayarrayWithObjects:navigationController1,navigationController2,nil]; self.viewControllers= controllers; self.selectedIndex= 0; |
在測試中發現:在iOS SDK6的環境下移動tabBar後,介面會留出空白,也就是說UITabBarController的tabBar的部分實際上是獨佔了該地區,即使強制將tabBar通過設定frame將tabBar移開,在該地區也不會顯示其他內容。關於這個問題,github上有一個解決方案:點擊查看
該方案代碼很簡潔:就是在移動tabBar之後,修改視圖的frame大小,問題看似解決了。
二,我為什麼沒有使用UITabBarController_setHidden
似乎UITabBarController_setHidden能夠解決問題,但在實際使用的時候發現一個問題,當使用pushViewController彈出一個UIViewController【配置hidesBottomBarWhenPushed=YES,頁面彈出時tabBar隱藏】,接著popViewControllerAnimated彈回時,tabBar會自動顯示並將所屬頁面的frame重新設定了。這樣,設定頁面frame的時機不好控制,另外這種方式在頁面切換的時候也會有些不太美觀的效果。
使用系統內建的tabBar或者navigationBar的好處是顯而易見的,不過在本例中的情形(需要手勢去隱藏顯示底部欄),使用自定的tabBar反而不好處理。
嘗試失敗之後,我決定使用自訂的tabBar,想要自訂tabBar,一個問題就是怎麼隱藏內建的tabBar。
三,如何隱藏UITabBarController內建的tabBar
網路上有方法:
self.tabBar.hidden = YES;
甚至是
[self.tabBar removeFromSuperview];
這些確實能實現隱藏tabBar的功能,但是隱藏了之後在tabBar原有的位置沒有填充上內容。正確的做法是:
將UITabBarController中的各個RootViewController進行如下設定:
self.homeViewController.hidesBottomBarWhenPushed = YES;
在我的工程中,還遇到了一個問題:即使設定了hidesBottomBarWhenPushed,在介面的底部還是留有一塊沒有內容的地區(正好是tabBar的地區)。經過查詢,發現原因是在添加主體UITabBarController到容器UIViewController的時候,使用了addChildViewController的方式,將addChildViewController去掉,只保留addSubview的方式,一切運行正常。
四,addChildViewController怎麼能影響到UITabBarController的tabBar
這個問題我暫時不清楚是由什麼造成的。但說到這裡了就談談我對addChildViewController這種方式的看法:使用addChildViewController的方式來處理本文描述的情境並沒有什麼好處。addChildViewController這種方式我感覺主要是為了能方便頁面切換(使用transitionFromViewController方法),而本情境中,並不是“兩個頁面切換”,而是左側欄和主體視圖一直都存在,只是通過手勢移開或者顯示各自的view而已。
之前我都是只使用addSubview將左側欄的view和主體view(都是UIController的view)依次添加到一個容器上,網路上有人說“[viewController.view addSubview:someOtherViewController.view];”這種方式其實對是UIViewController的誤用,因為這麼做“將不會觸發被加入view hierarchy的view的controller的viewWillAppear:方法”。
IOS研究之UITabBarController隱藏tabBar以及addChildViewController