在iOS開發(fā)中,經(jīng)常需要從一個(gè)無NavigationBar的控制器push到一個(gè)有NavigationBar的控制器,或者相反??此浦灰O(shè)置一下NavigationBar的Hidden屬性就可以了,其實(shí)里面還有不少坑。
隱藏導(dǎo)航欄的方法很簡(jiǎn)單,只要在控制器將要出現(xiàn)的時(shí)候設(shè)置NavigationBar隱藏就可以了,然后在控制器將要消失的時(shí)候重新顯示NavigationBar,效果如圖1所示。
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
// 隱藏導(dǎo)航欄方法1
self.navigationController.navigationBarHidden = YES;
// 方法2
// [self.navigationController setNavigationBarHidden:YES];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[self.navigationController setNavigationBarHidden:NO];
}

但是仔細(xì)觀察會(huì)發(fā)現(xiàn)切換的過程并不順滑:1.有導(dǎo)航欄的控制器出現(xiàn)時(shí),導(dǎo)航欄會(huì)立即出現(xiàn),而控制器的View是自右向左漸入的(簡(jiǎn)書其實(shí)就是這樣的);2.點(diǎn)擊返回按鈕時(shí),導(dǎo)航欄消失且右側(cè)會(huì)出現(xiàn)黑邊。如圖2所示。

因?yàn)樵趐ush頁(yè)面的時(shí)候,animated屬性是設(shè)置成YES的,所以控制器View的出現(xiàn)會(huì)有動(dòng)畫。animated屬性通常都是設(shè)置成YES的,這樣的頁(yè)面切換會(huì)讓人比較舒服。
[self.navigationController pushViewController:[[HQThirdViewController alloc] init] animated:YES];
所以我們猜想一下,導(dǎo)航欄的顯示和隱藏是不是也應(yīng)該有個(gè)animated屬性。果不其然,設(shè)置導(dǎo)航欄隱藏還有另一個(gè)方法可以開啟和關(guān)閉動(dòng)畫,我們開啟動(dòng)畫之后再看看效果,如圖3。
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.navigationController setNavigationBarHidden:YES animated:YES];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[self.navigationController setNavigationBarHidden:NO animated:YES];
}

導(dǎo)航欄的顯示和控制器的View顯示都有動(dòng)畫了,pop的時(shí)候也不會(huì)出現(xiàn)黑邊了。這個(gè)animated屬性官方是這樣解釋的:*If animated, it will transition vertically using UINavigationControllerHideShowBarDuration. *意思就是說如果開啟動(dòng)畫,導(dǎo)航欄會(huì)以某個(gè)時(shí)長(zhǎng)進(jìn)行垂直過渡。
對(duì)于UINavigationControllerHideShowBarDuration官方文檔也給出了解釋:*This variable specifies the duration when animating the navigation bar. Note that this is a constant value, so it cannot be set. *就是說UINavigationControllerHideShowBarDuration決定了導(dǎo)航欄動(dòng)畫的時(shí)長(zhǎng),注意這是一個(gè)常量,不能被改變。
這樣就完美解決了嗎?不,另一個(gè)坑出現(xiàn)了。點(diǎn)擊TabBarItem進(jìn)入"我的"頁(yè)面的時(shí)候,導(dǎo)航欄也出現(xiàn)了動(dòng)畫,因?yàn)閯?dòng)畫只能寫在ViewWillAppear方法里,所以每次顯示頁(yè)面都會(huì)調(diào)用。

現(xiàn)在這種情況下,animated屬性肯定是不能開啟的,但是pop時(shí)候的黑邊問題又該怎么解決?
解決方法1
首先想想為什么pop的時(shí)候?qū)Ш綑谥苯泳拖Я耍驗(yàn)轫?xiàng)目中我把導(dǎo)航欄的translucent屬性關(guān)閉了(這個(gè)屬性默認(rèn)是開啟的),控制器的View不會(huì)有穿透效果,而pop的時(shí)候?qū)Ш綑陔[藏又沒有開啟動(dòng)畫效果,所以就導(dǎo)致了導(dǎo)航欄直接消失。那么我們?cè)賮砜纯撮_啟translucent屬性的效果,如圖5。

黑邊不會(huì)再出現(xiàn)了,導(dǎo)航欄依舊是立即消失,但是控制器的View填充了整個(gè)畫面。這是一種解決方法,大家可以看看釘釘iOS客戶端,從設(shè)置頁(yè)面pop回我的頁(yè)面也是這種效果。
最后,如果希望Pop的時(shí)候?qū)Ш綑诓粫?huì)立即消失而且沒有黑邊,切換TabBarItem的時(shí)候又不會(huì)出現(xiàn)動(dòng)畫,那么依舊還是要開啟animated屬性的。
解決方法2
1.給"我的"控制器.h文件里添加一個(gè)關(guān)閉動(dòng)畫的屬性
@interface HQMineViewController : UITableViewController
@property (nonatomic, assign) BOOL closeAnimating;
@end
2.在自定義的TabBarController里面實(shí)現(xiàn)UITabBarControllerDelegate,并實(shí)現(xiàn)如下方法
@interface HQTabBarController ()<UITabBarControllerDelegate>
@end
@implementation HQTabBarController
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController
{
UINavigationController *navigationController = (UINavigationController *)viewController;
if ([navigationController.topViewController isKindOfClass:[HQMineViewController class]])
{
HQMineViewController *mineVc = (HQMineViewController *)navigationController.topViewController;
// 點(diǎn)擊TabBarItem進(jìn)入"我的"控制器 會(huì)關(guān)閉導(dǎo)航欄消失的動(dòng)畫
mineVc.closeAnimating = YES;
}
return YES;
}
}
3.修改"我的"控制器中隱藏導(dǎo)航欄的方法
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.navigationController setNavigationBarHidden:YES animated:!self.closeAnimating];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[self.navigationController setNavigationBarHidden:NO animated:YES];
// 控制器消失時(shí)要開啟動(dòng)畫,保證由其他方式進(jìn)入控制器會(huì)有動(dòng)畫
self.closeAnimating = NO;
}
4.最終效果如圖6所示

解決方法3
走了這么多的彎路,接下來就放出最終解決方法了,其實(shí)只要將animated屬性繼承ViewWillAppear(Disappear)的animated屬性即可,恍然大悟。
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.navigationController setNavigationBarHidden:YES animated:animated];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[self.navigationController setNavigationBarHidden:NO animated:animated];
}
總結(jié)
方法3最簡(jiǎn)單,又能完美解決NavigationBar顯示和隱藏切換的問題,順便簡(jiǎn)單地實(shí)現(xiàn)了tableHeaderView的下拉放大。