導(dǎo)航欄顯示和隱藏的坑

在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];
}
圖1.gif

但是仔細(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所示。

圖2.gif

因?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];
}
圖3.gif

導(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)用。

圖4.gif

現(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。

圖5.gif

黑邊不會(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所示

圖6.gif

解決方法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的下拉放大。

代碼下載地址

點(diǎn)擊進(jìn)入Github

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,103評(píng)論 4 61
  • 有感 ....請(qǐng)?jiān)试S我在文章開篇爆句粗口, 就這導(dǎo)航欄錯(cuò)亂這 Bug, 我真日了狗了. 自從測(cè)試小伙伴發(fā)現(xiàn)這個(gè)問...
    李國(guó)安閱讀 6,580評(píng)論 59 108
  • Swift版本點(diǎn)擊這里歡迎加入QQ群交流: 594119878最新更新日期:18-09-17 About A cu...
    ylgwhyh閱讀 25,998評(píng)論 7 249
  • 有個(gè)朋友說人家?guī)硗邪嗟脑?,一個(gè)小孩多少錢算給人家,所以后來我就跟對(duì)方說,不想占人家便宜(人家?guī)兔春⒆拥脑挘?,?..
    臨在一刻閱讀 262評(píng)論 0 0
  • 蔚來汽車、摩拜董事長(zhǎng)給大家講解《重新定義用戶體驗(yàn)》 李斌認(rèn)為商業(yè)化的本質(zhì)就是差異化用戶體驗(yàn)。重新定義用戶體驗(yàn),就能...
    Joycty閱讀 908評(píng)論 0 1

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