迷之“導(dǎo)航欄”

對于iOS 開發(fā)者來說,導(dǎo)航欄確實是一個讓人困惑的知識點碗啄。比如設(shè)置導(dǎo)航欄透明效果,透明導(dǎo)航欄與非透明導(dǎo)航欄之間的跳轉(zhuǎn)等等,我開始也是在項目預(yù)定的框架 下去設(shè)置導(dǎo)航欄的一些屬性米苹,直到我負責的模塊在IOS10中出現(xiàn)了導(dǎo)航欄的bug的時候才不得不 去好好消化這一塊,去理解系統(tǒng)在導(dǎo)航切換時的一些特效砰琢,去調(diào)研市面上常用APP對于導(dǎo)航欄 的一些處理蘸嘶,這里我就來分解一下導(dǎo)航欄的奧秘。

導(dǎo)航欄基礎(chǔ)

iOS 導(dǎo)航欄大致有兩部分組成:navigationBar和navigationItem:

  • navigationBar
    navigationBar是navigationController的一部分陪汽,它不屬于單個的UIViewController训唱。我們在同一個navigationController中push或者pop的時候,看到的bar其實都是一個掩缓,也就是說雪情,在一個viewController中修改了bar的屬性之后在其他的控制器中也是可見的。

在考慮設(shè)置導(dǎo)航欄的時候你辣,我們通常也是一起設(shè)置了App的狀態(tài)欄(也就是電池條)巡通,IOS有兩個常用的 狀態(tài)欄(statusBarStyle)屬性,分別是:

在考慮設(shè)置導(dǎo)航欄的時候舍哄,我們通常也是一起設(shè)置了App的狀態(tài)欄(也就是電池條)宴凉,IOS有兩個常用的 狀態(tài)欄(statusBarStyle)屬性,分別是:

// Dark content, for use on light backgrounds
UIStatusBarStyleDefault         = 0,
// Light content, for use on dark backgrounds
UIStatusBarStyleLightContent     NS_ENUM_AVAILABLE_IOS(7_0) = 1,

導(dǎo)航欄始終處于狀態(tài)欄的下方表悬,我們可以看到幾乎所有的App導(dǎo)航欄和狀態(tài)欄的顏色 都相同弥锄,這樣的效果無法通過設(shè)置導(dǎo)航欄的backgroundColor得到,因為導(dǎo)航欄y坐標為20蟆沫, 狀態(tài)欄籽暇,設(shè)置了導(dǎo)航欄的背景色不會影響到狀態(tài)欄。但是神奇的是饭庞,導(dǎo)航欄上面還有一層 View是navigationBarBackground(設(shè)置barTintColor將改變此背景色)戒悠,其y坐標為-20,剛好把狀態(tài)欄覆蓋舟山,所以我們使用setBackgroundImage就可以保證導(dǎo)航欄與狀態(tài)欄同色绸狐,如下:

UIImage *colorImage = [UIImage imageWithColor:[UIColor clearColor] size:CGSizeMake(1, 1)];
[navc.navigationBar setBackgroundImage:colorImage forBarMetrics:UIBarMetricsDefault];
[navc.navigationBar setShadowImage:colorImage];

navigationItem

我們強調(diào)了navigationBar是屬于navigationController的一部分卤恳,那么navigationItem 卻是屬于UIViewCOntroller的一部分,這一點在剛開始很容易造成困惑寒矿,這些個Item明明 就在Bar上突琳,為什么偏偏屬于ViewController,但是事實就是這樣符相。navigationItem由三部分 組成拆融,分別是:
titleView
這又是一個讓我們疑惑的屬性,按照常理我們認為這是一個UILabel主巍,通過設(shè)置navigationItem. titleView就是可以搞定title的一切屬性冠息,但是事實是我們想錯了,這個屬性默認為空孕索。所以 當我們要單獨考慮一個viewController的title的時候逛艰,就需要為其設(shè)置一個UILabel作為 titleView了,如下所示:

- (void)setTitle:(NSString *)title titleColor:(UIColor *)color{
UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 44)];
titleLabel.text     = title;
titleLabel.font     = [UIFont boldSystemFontOfSize:20.f];
titleLabel.textAlignment  = NSTextAlignmentCenter;
titleLabel.textColor    = color;
self.navigationItem.titleView = titleLabel;
}

leftNavigationItem

同上搞旭,其默認也為空(雖然系統(tǒng)會默認生成“返回”散怖,但這個屬性值依然為空)。所以我們一般 會設(shè)置可控的leftNavigationItem肄渗,如下:

- (void)setNavBarCustomBackButton:(NSString *)title target:(id)target action:(SEL)action {
UIImage *image = [UIImage imageSVGNamed:@"icon_arrow_back_white" size:CGSizeMake(20, 20) cache:YES];

UIButton *buttonItem = [UIButton buttonWithType:UIButtonTypeSystem];
buttonItem.tag = 1002;
buttonItem.titleLabel.font = [UIFont systemFontOfSize:16.0];
buttonItem.imageEdgeInsets = UIEdgeInsetsMake(0, -16, 0, 0);
buttonItem.titleEdgeInsets = UIEdgeInsetsMake(0, -19, 0, 0);
[buttonItem setImage:image forState:UIControlStateNormal];
[buttonItem setTitle:title forState:UIControlStateNormal];
[buttonItem setTitleColor:RGB(45, 45, 45) forState:UIControlStateNormal];
[buttonItem addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
[buttonItem sizeToFit];
buttonItem.frame = CGRectMake(0, 0, buttonItem.frame.size.width, 40);

self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:buttonItem];
}

rightNavigationItem

其設(shè)置與leftNavigationItem一樣镇眷,這里不啰嗦了。
對于navigationItem的三個屬性來說翎嫡,其貫穿與整個App的開發(fā)過程中欠动,我們?yōu)榱舜a的整潔性, 一般不會在viewController中直接設(shè)置惑申,而已通過category來使用具伍。

導(dǎo)航欄切換

iOS10中navigationController的push和pop,前后兩個viewController如果導(dǎo)航欄顏色(或者透明度)不一致圈驼, 就會出現(xiàn)導(dǎo)航欄的切換動畫人芽,處理這種情況時應(yīng)該特別小心,如果處理不當就會造成bug或者 App體驗上的損失绩脆。
系統(tǒng)默認在導(dǎo)航欄切換的時候會有動畫和毛玻璃效果萤厅,其實這個動畫就是前后Controller的 導(dǎo)航欄顏色的漸變動畫,而且title也會隨著動畫產(chǎn)生“隱去”和“隱現(xiàn)”的效果靴迫,這種效果在 一般情況下沒有問題惕味,而且看起來還很不錯,但是下列兩種情況下你應(yīng)該單獨考慮玉锌。

一側(cè)透明一側(cè)不透明

這種情況下就會產(chǎn)生奇怪的效果名挥,一側(cè)根本看不見導(dǎo)航欄,而系統(tǒng)給我們的是一個漸變的動畫芬沉, 然而這個動畫仿佛在iOS10上有bug躺同,會發(fā)生跳轉(zhuǎn)閃爍的情況(在viewWillAppear中設(shè)置導(dǎo)航欄 背景Image的效果會推遲顯示)。如果我們可以接受這個動畫丸逸,但是絕不能接受這個閃爍發(fā)生蹋艺, 可以嘗試著修復(fù)這個bug;但是一些情況下我們并不期望這個動畫產(chǎn)生黄刚,做法很簡單把透明一側(cè) 的導(dǎo)航欄直接隱藏掉捎谨,這樣前后viewController的導(dǎo)航欄漸進動畫就會消失,很多blog上面 說的就是這種方法憔维。
如果在透明一側(cè)的導(dǎo)航欄的透明度是隨著scrollView的contentOffset來變化的涛救,那么隱藏導(dǎo)航欄這種 解決辦法就會失效,因為我們不能魯莽地去隱藏掉一個透明度不為0的導(dǎo)航欄业扒。這種情況下是 逼著我們?nèi)崿F(xiàn)自定義的轉(zhuǎn)場動畫检吆,或者修復(fù)ios10上的bug,這兩種解決辦法都不會太簡單程储, 我會接下來講解蹭沛。

兩側(cè)主題相差巨大

如果兩側(cè)導(dǎo)航欄的主題風(fēng)格相差巨大,也就是說前后兩個viewController根本不像是同一個 navigationController中的子congtoller章鲤,那么系統(tǒng)中的漸變動畫就會顯得很不協(xié)調(diào)摊灭,想想 在漸變動畫中出現(xiàn)一個其它不相干的顏色是多么的抓狂。這里的解決辦法也有兩種败徊,一種原理很簡單 帚呼,就是在一側(cè)放棄使用系統(tǒng)的導(dǎo)航欄,而偽造一個假的導(dǎo)航欄皱蹦,這樣就不會產(chǎn)生漸變動畫煤杀。另一種 方法還是自己實現(xiàn)轉(zhuǎn)場動畫,又回到了這個問題根欧。
市面上一些大的App怜珍,在處理上面兩種情況的時候都放棄了系統(tǒng)的漸變動畫,而是采用一種涇渭分明的 轉(zhuǎn)場方式凤粗,比如說今日頭條酥泛、支付寶等,具體是使用偽導(dǎo)航欄還是自己實現(xiàn)的轉(zhuǎn)場動畫就不得而知了嫌拣。 特別說明:以上情況可能不適用于ios10之前柔袁,小心調(diào)試吧。

Appearance主題

上面已經(jīng)討論過异逐,為navigationBar上面的item設(shè)置屬性往往會造成困擾捶索,我們有時候無法直接 改變這些item的屬性,所以需要設(shè)置自定義item灰瞻。Appearance主題是為了設(shè)置整個App的默認屬性腥例, 特別是對于UINavigation有用辅甥,能夠設(shè)置App導(dǎo)航欄的色彩基調(diào)。如下:

[[UINavigationBar appearance] setTintColor:RGB(0x51, 0x4e, 0x4e)];
[[UINavigationBar appearance] setBarTintColor:RGB(0, 191, 143)];
[[UINavigationBar appearance] setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[UIFont systemFontOfSize:15], NSFontAttributeName, [UIColor whiteColor], NSForegroundColorAttributeName, nil]];
[[UIBarButtonItem appearance] setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:
                                                              [UIFont systemFontOfSize:15.0], NSFontAttributeName,
                                                              RGB(0x51, 0x4e, 0x4e), NSForegroundColorAttributeName,
                                                              nil]
                                                    forState:UIControlStateNormal];
[[UINavigationBar appearance] setBackIndicatorImage:[UIImage imageSVGNamed:@"icon_arrow_back_white" size:CGSizeMake(20, 20) cache:YES]];
[[UINavigationBar appearance] setBackIndicatorTransitionMaskImage:[UIImage imageSVGNamed:@"icon_arrow_back_white" size:CGSizeMake(20, 20) cache:YES]];

上述代碼最好在App啟動的時候就設(shè)置好燎竖,作為導(dǎo)航欄的默認設(shè)置璃弄,而且在項目的進行過程中不要輕易地再去更改。 如果確實有需求更改navigationBar上的屬性构回,記得在viewWillAppear或者viewWillDisappear中修改 回去夏块,或者直接使用自定義的item。

總結(jié)

這里我不打算去講解IOS的轉(zhuǎn)場動畫了纤掸,因為這個題目還是很大的脐供,我怕說不清楚;再者除非對細節(jié)有著很高的要求借跪,一般APP也不會去做 導(dǎo)航欄的轉(zhuǎn)場動畫政己。針對,IOS10中出現(xiàn)的導(dǎo)航欄閃爍問題掏愁,我們組的大牛的解決辦法是匹颤,放棄NavigationBar上面的一層backgroundView, 統(tǒng)一設(shè)置成clearColor托猩,然后在navigationBar上自己加一層layer印蓖,來模擬漸變動畫,這樣就通過擴展NavigationBar京腥,避開了系統(tǒng)導(dǎo)航欄 的一些默認處理效果赦肃。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市公浪,隨后出現(xiàn)的幾起案子他宛,更是在濱河造成了極大的恐慌,老刑警劉巖欠气,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件厅各,死亡現(xiàn)場離奇詭異,居然都是意外死亡预柒,警方通過查閱死者的電腦和手機队塘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來宜鸯,“玉大人憔古,你說我怎么就攤上這事×苄洌” “怎么了鸿市?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我焰情,道長陌凳,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任内舟,我火速辦了婚禮冯遂,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘谒获。我一直安慰自己,他們只是感情好壁却,可當我...
    茶點故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布批狱。 她就那樣靜靜地躺著,像睡著了一般展东。 火紅的嫁衣襯著肌膚如雪赔硫。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天盐肃,我揣著相機與錄音爪膊,去河邊找鬼。 笑死砸王,一個胖子當著我的面吹牛推盛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播谦铃,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼耘成,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了驹闰?” 一聲冷哼從身側(cè)響起瘪菌,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎嘹朗,沒想到半個月后师妙,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡屹培,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年默穴,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片褪秀。...
    茶點故事閱讀 40,664評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡壁顶,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出溜歪,到底是詐尸還是另有隱情若专,我是刑警寧澤,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布蝴猪,位于F島的核電站调衰,受9級特大地震影響膊爪,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜嚎莉,卻給世界環(huán)境...
    茶點故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一米酬、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧趋箩,春花似錦赃额、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至竹勉,卻和暖如春飞盆,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背次乓。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工吓歇, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人票腰。 一個月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓城看,卻偏偏與公主長得像,于是被迫代替她去往敵國和親杏慰。 傳聞我的和親對象是個殘疾皇子析命,可洞房花燭夜當晚...
    茶點故事閱讀 45,675評論 2 359

推薦閱讀更多精彩內(nèi)容

  • 對于初學(xué)者來說,IOS中的導(dǎo)航欄確實是一個讓人困惑的知識點逃默,我開始也是在項目預(yù)定的框架下去設(shè)置導(dǎo)航欄的一些屬性鹃愤,直...
    myzhing閱讀 392評論 0 1
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件完域、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,121評論 4 61
  • { 11软吐、核心動畫 需要簽協(xié)議,但是系統(tǒng)幫簽好 一吟税、CABasicAnimation 1凹耙、創(chuàng)建基礎(chǔ)動畫對象 CAB...
    CYC666閱讀 1,557評論 2 4
  • 媽媽: 您還好嗎? 轉(zhuǎn)眼間您已經(jīng)離開我一百多天了肠仪,我非常想念您肖抱,您可知道? 您離世后我總夢...
    楊靜相伴要你好看閱讀 379評論 4 2
  • 1拌屏、 去太太家吃飯术荤,開空調(diào)很喛和 2倚喂、回來時跟老公鬧別扭了瓣戚,生氣中…我在想我是否真的所有的事都依著他來? 3子库、去超...
    寧靜的流星閱讀 86評論 0 0