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

對(duì)于初學(xué)者來(lái)說(shuō)研底,IOS中的導(dǎo)航欄確實(shí)是一個(gè)讓人困惑的知識(shí)點(diǎn),我開(kāi)始也是在項(xiàng)目預(yù)定的框架
下去設(shè)置導(dǎo)航欄的一些屬性步清,直到我負(fù)責(zé)的模塊在IOS10中出現(xiàn)了導(dǎo)航欄的bug的時(shí)候才不得不
去好好消化這一塊要门,去理解系統(tǒng)在導(dǎo)航切換時(shí)的一些特效,去調(diào)研市面上常用APP對(duì)于導(dǎo)航欄
的一些處理廓啊,這里我就來(lái)分解一下導(dǎo)航欄的奧秘欢搜。

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

我們見(jiàn)到的導(dǎo)航欄大致由兩部分組成,分別是navigationBar和navigationItem谴轮。

  • navigationBar

豪無(wú)疑問(wèn)navigationBar是屬于navigationController的一部分炒瘟,其不屬于單個(gè)的UIViewController
我們?cè)谕粋€(gè)navigationController中push或者pop的時(shí)候,看到的Bar其實(shí)都是同一個(gè)第步,也就是
說(shuō)疮装,在一個(gè)ViewController中修改了Bar在其它的ViewController中也是可見(jiàn)的。

在考慮設(shè)置導(dǎo)航欄的時(shí)候粘都,我們通常也是一起設(shè)置了App的狀態(tài)欄(也就是電池條)廓推,IOS有兩個(gè)常用的
狀態(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)欄的顏色
都相同樊展,這樣的效果無(wú)法通過(guò)設(shè)置導(dǎo)航欄的backgroundColor得到,因?yàn)閷?dǎo)航欄y坐標(biāo)為20堆生,
狀態(tài)欄专缠,設(shè)置了導(dǎo)航欄的背景色不會(huì)影響到狀態(tài)欄。但是神奇的是淑仆,導(dǎo)航欄上面還有一層
View是navigationBarBackground(設(shè)置barTintColor將改變此背景色)涝婉,其y坐標(biāo)為-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

我們強(qiáng)調(diào)了navigationBar是屬于navigationController的一部分省骂,那么navigationItem
卻是屬于UIViewCOntroller的一部分,這一點(diǎn)在剛開(kāi)始很容易造成困惑最住,這些個(gè)Item明明
就在Bar上钞澳,為什么偏偏屬于ViewController,但是事實(shí)就是這樣涨缚。navigationItem由三部分
組成轧粟,分別是:

  1. titleView

這又是一個(gè)讓我們疑惑的屬性,按照常理我們認(rèn)為這是一個(gè)UILabel脓魏,通過(guò)設(shè)置navigationItem.
titleView就是可以搞定title的一切屬性兰吟,但是事實(shí)是我們想錯(cuò)了,這個(gè)屬性默認(rèn)為空茂翔。所以
當(dāng)我們要單獨(dú)考慮一個(gè)viewController的title的時(shí)候混蔼,就需要為其設(shè)置一個(gè)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;
}
  1. leftNavigationItem

同上珊燎,其默認(rèn)也為空(雖然系統(tǒng)會(huì)默認(rèn)生成“返回”惭嚣,但這個(gè)屬性值依然為空)。所以我們一般
會(huì)設(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];
}
  1. rightNavigationItem

其設(shè)置與leftNavigationItem一樣晚吞,這里不啰嗦了。

對(duì)于navigationItem的三個(gè)屬性來(lái)說(shuō)谋国,其貫穿與整個(gè)App的開(kāi)發(fā)過(guò)程中槽地,我們?yōu)榱舜a的整潔性,
一般不會(huì)在viewController中直接設(shè)置芦瘾,而已通過(guò)category來(lái)使用捌蚊。

導(dǎo)航欄切換

iOS10中navigationController的push和pop,前后兩個(gè)viewController如果導(dǎo)航欄顏色(或者透明度)不一致近弟,
就會(huì)出現(xiàn)導(dǎo)航欄的切換動(dòng)畫(huà)缅糟,處理這種情況時(shí)應(yīng)該特別小心,如果處理不當(dāng)就會(huì)造成bug或者
App體驗(yàn)上的損失藐吮。

系統(tǒng)默認(rèn)在導(dǎo)航欄切換的時(shí)候會(huì)有動(dòng)畫(huà)和毛玻璃效果,其實(shí)這個(gè)動(dòng)畫(huà)就是前后Controller的
導(dǎo)航欄顏色的漸變動(dòng)畫(huà)逃贝,而且title也會(huì)隨著動(dòng)畫(huà)產(chǎn)生“隱去”和“隱現(xiàn)”的效果谣辞,這種效果在
一般情況下沒(méi)有問(wèn)題,而且看起來(lái)還很不錯(cuò)沐扳,但是下列兩種情況下你應(yīng)該單獨(dú)考慮泥从。

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

這種情況下就會(huì)產(chǎn)生奇怪的效果,一側(cè)根本看不見(jiàn)導(dǎo)航欄沪摄,而系統(tǒng)給我們的是一個(gè)漸變的動(dòng)畫(huà)躯嫉,
然而這個(gè)動(dòng)畫(huà)仿佛在iOS10上有bug纱烘,會(huì)發(fā)生跳轉(zhuǎn)閃爍的情況(在viewWillAppear中設(shè)置導(dǎo)航欄
背景Image的效果會(huì)推遲顯示)。如果我們可以接受這個(gè)動(dòng)畫(huà)祈餐,但是絕不能接受這個(gè)閃爍發(fā)生擂啥,
可以嘗試著修復(fù)這個(gè)bug;但是一些情況下我們并不期望這個(gè)動(dòng)畫(huà)產(chǎn)生帆阳,做法很簡(jiǎn)單把透明一側(cè)
的導(dǎo)航欄直接隱藏掉哺壶,這樣前后viewController的導(dǎo)航欄漸進(jìn)動(dòng)畫(huà)就會(huì)消失,很多blog上面
說(shuō)的就是這種方法蜒谤。

如果在透明一側(cè)的導(dǎo)航欄的透明度是隨著scrollView的contentOffset來(lái)變化的山宾,那么隱藏導(dǎo)航欄這種
解決辦法就會(huì)失效,因?yàn)槲覀儾荒荇斆У厝ル[藏掉一個(gè)透明度不為0的導(dǎo)航欄鳍徽。這種情況下是
逼著我們?nèi)?shí)現(xiàn)自定義的轉(zhuǎn)場(chǎng)動(dòng)畫(huà)资锰,或者修復(fù)ios10上的bug,這兩種解決辦法都不會(huì)太簡(jiǎn)單阶祭,
我會(huì)在接下來(lái)的文章中講解绷杜。

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

如果兩側(cè)導(dǎo)航欄的主題風(fēng)格相差巨大,也就是說(shuō)前后兩個(gè)viewController根本不像是同一個(gè)
navigationController中的子congtoller胖翰,那么系統(tǒng)中的漸變動(dòng)畫(huà)就會(huì)顯得很不協(xié)調(diào)接剩,想想
在漸變動(dòng)畫(huà)中出現(xiàn)一個(gè)其它不相干的顏色是多么的抓狂。這里的解決辦法也有兩種萨咳,一種原理很簡(jiǎn)單
懊缺,就是在一側(cè)放棄使用系統(tǒng)的導(dǎo)航欄,而偽造一個(gè)假的導(dǎo)航欄培他,這樣就不會(huì)產(chǎn)生漸變動(dòng)畫(huà)鹃两。另一種
方法還是自己實(shí)現(xiàn)轉(zhuǎn)場(chǎng)動(dòng)畫(huà),又回到了這個(gè)問(wèn)題舀凛。

市面上一些大的App俊扳,在處理上面兩種情況的時(shí)候都放棄了系統(tǒng)的漸變動(dòng)畫(huà),而是采用一種涇渭分明的
轉(zhuǎn)場(chǎng)方式猛遍,比如說(shuō)今日頭條馋记、支付寶等,具體是使用偽導(dǎo)航欄還是自己實(shí)現(xiàn)的轉(zhuǎn)場(chǎng)動(dòng)畫(huà)就不得而知了懊烤。
特別說(shuō)明:以上情況可能不適用于ios10之前梯醒,小心調(diào)試吧。

Appearance主題

上面已經(jīng)討論過(guò)腌紧,為navigationBar上面的item設(shè)置屬性往往會(huì)造成困擾茸习,我們有時(shí)候無(wú)法直接
改變這些item的屬性,所以需要設(shè)置自定義item壁肋。Appearance主題是為了設(shè)置整個(gè)App的默認(rèn)屬性号胚,
特別是對(duì)于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]];

上述代碼最好在A(yíng)pp啟動(dòng)的時(shí)候就設(shè)置好猫胁,作為導(dǎo)航欄的默認(rèn)設(shè)置箱亿,而且在項(xiàng)目的進(jìn)行過(guò)程中不要輕易地再去更改。
如果確實(shí)有需求更改navigationBar上的屬性杜漠,記得在viewWillAppear或者viewWillDisappear中修改
回去极景,或者直接使用自定義的item。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末驾茴,一起剝皮案震驚了整個(gè)濱河市盼樟,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌锈至,老刑警劉巖晨缴,帶你破解...
    沈念sama閱讀 221,635評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異峡捡,居然都是意外死亡击碗,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)们拙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)稍途,“玉大人,你說(shuō)我怎么就攤上這事砚婆⌒蹬模” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,083評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵装盯,是天一觀(guān)的道長(zhǎng)坷虑。 經(jīng)常有香客問(wèn)我,道長(zhǎng)埂奈,這世上最難降的妖魔是什么迄损? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,640評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮账磺,結(jié)果婚禮上芹敌,老公的妹妹穿的比我還像新娘。我一直安慰自己垮抗,他們只是感情好氏捞,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著借宵,像睡著了一般幌衣。 火紅的嫁衣襯著肌膚如雪矾削。 梳的紋絲不亂的頭發(fā)上壤玫,一...
    開(kāi)封第一講書(shū)人閱讀 52,262評(píng)論 1 308
  • 那天豁护,我揣著相機(jī)與錄音,去河邊找鬼欲间。 笑死楚里,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的猎贴。 我是一名探鬼主播班缎,決...
    沈念sama閱讀 40,833評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼她渴!你這毒婦竟也來(lái)了达址?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,736評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤趁耗,失蹤者是張志新(化名)和其女友劉穎沉唠,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體苛败,經(jīng)...
    沈念sama閱讀 46,280評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡满葛,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了罢屈。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片嘀韧。...
    茶點(diǎn)故事閱讀 40,503評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖缠捌,靈堂內(nèi)的尸體忽然破棺而出锄贷,到底是詐尸還是另有隱情,我是刑警寧澤鄙币,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布肃叶,位于F島的核電站,受9級(jí)特大地震影響十嘿,放射性物質(zhì)發(fā)生泄漏因惭。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評(píng)論 3 333
  • 文/蒙蒙 一绩衷、第九天 我趴在偏房一處隱蔽的房頂上張望蹦魔。 院中可真熱鬧,春花似錦咳燕、人聲如沸勿决。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,340評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)低缩。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間咆繁,已是汗流浹背讳推。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,460評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留玩般,地道東北人银觅。 一個(gè)月前我還...
    沈念sama閱讀 48,909評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像坏为,于是被迫代替她去往敵國(guó)和親究驴。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評(píng)論 2 359

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