iOS 導(dǎo)航欄的那些事兒

最近項(xiàng)目里有個(gè)需求和導(dǎo)航欄的樣式定制有關(guān),深入之后發(fā)現(xiàn)之前理解的一些概念有些模糊,剛好趁著這次機(jī)會(huì)全面整理了一下。

從 iOS7 開(kāi)始,蘋(píng)果采用了大量的扁平化和毛玻璃風(fēng)格,剛升級(jí)到 iOS7 之后會(huì)發(fā)現(xiàn)界面的布局多多少少有一些偏差(當(dāng)然現(xiàn)在新建的項(xiàng)目沒(méi)有這方面困擾,不需要經(jīng)歷6到7的適配),適配過(guò)程中會(huì)發(fā)現(xiàn)如下一些屬性,

-edgesForExtendedLayout

-translucent

-extendedLayoutIncludesOpaqueBars

-automaticallyAdjustsScrollViewInsets

根據(jù)字面意思看上去這些屬性很好理解,但是發(fā)現(xiàn)他們組合之后會(huì)有一些不同的表現(xiàn),一些奇怪的問(wèn)題也不知道什么原因?qū)е碌摹2挥脫?dān)心,接下去我會(huì)全面的解析一下這幾個(gè)屬性的含義,保證你再也不怕各種奇怪的導(dǎo)航欄問(wèn)題啦。

edgesForExtendedLayout + translucent

iOS7 以后,edgesForExtendedLayout 的默認(rèn)設(shè)置是 UIRectEdgeAll,translucent 的默認(rèn)值是 true。這種組合會(huì)使 rootView 的布局從(0,0)開(kāi)始,即 view 的內(nèi)容會(huì)被導(dǎo)航欄遮擋住,大多數(shù)情況下將 edgesForExtendedLayout 修改為 UIRectEdgeNone 就能解決布局被遮擋的問(wèn)題。將 translucent 設(shè)置成 false 也會(huì)使 rootView 從導(dǎo)航欄底部開(kāi)始,但是 translucent = false 時(shí)即使將 edgesForExtendedLayout 再改成 UIRectEdgeAll rootView 還是從導(dǎo)航欄底部開(kāi)始布局。如何可以在導(dǎo)航欄不透明的情況下讓 rootView 從(0,0)開(kāi)始布局呢?蘋(píng)果也考慮到了這種需求,提供了 extendedLayoutIncludesOpaqueBars 這個(gè)屬性。

小結(jié):translucent 為 true,rootView 從(0,0)開(kāi)始布局,修改 edgesForExtendedLayout 屬性可以改變布局;translucent 為 false,rootView 從導(dǎo)航欄底部開(kāi)始布局,修改 edgesForExtendedLayout 屬性無(wú)法改變布局。

extendedLayoutIncludesOpaqueBars + translucent

前面我們知道了 translucent 為 false 時(shí),修改 edgesForExtendedLayout 也無(wú)法使 rootView 從(0,0)開(kāi)始布局。蘋(píng)果為此提供了 extendedLayoutIncludesOpaqueBars,字面上理解的意思就是在不透明的導(dǎo)航欄下也全屏顯示。

這里多提一點(diǎn),在 ViewController 的生命周期中有 viewDidLoad,viewWillAppear,viewDidAppear,viewWillDisappear,viewDidDisappear,上述提到的這些屬性需要在 viewDidAppear 之前設(shè)置好,viewDidAppear 可以認(rèn)為系統(tǒng)已經(jīng)根據(jù)配置布局好了,在這里展示給用戶(hù)看。

automaticallyAdjustsScrollViewInsets

automaticallyAdjustsScrollViewInsets 默認(rèn)值是 true,表示在全屏模式下會(huì)自動(dòng)修改第一個(gè)添加到 rootView 的 scrollview 的 contentInset 為(64,0,0,0),這樣 scrollview 就不會(huì)被導(dǎo)航欄遮擋了。

關(guān)于 scrollview 有一個(gè)問(wèn)題比較常見(jiàn),這里解析一下原因。我們經(jīng)常會(huì)這么使用一個(gè) tableView,


-(void)viewDidLoad{

[superviewDidLoad];

// Do any additional setup after loading the view.

self.view.backgroundColor=[UIColorgreenColor];

self.navigationItem.title=@"Master";

self.tableView=[[UITableViewalloc]initWithFrame:self.view.bounds];

_tableView.backgroundColor=[UIColorwhiteColor];

_tableView.delegate=self;

_tableView.dataSource=self;

[self.viewaddSubview:_tableView];

}

這樣在默認(rèn)情況下(translucent = true, edgesForExtendedLayout = UIRectEdgeAll),tableView的顯示沒(méi)有問(wèn)題。但是當(dāng)我們將 edgesForExtendedLayout 設(shè)置成 UIRectEdgeNone 時(shí),當(dāng) tableView 的內(nèi)容比較多時(shí)底部的內(nèi)容反而顯示不下。這就很奇怪了,按照前面的結(jié)論,這時(shí)候 tableView是從導(dǎo)航欄底部開(kāi)始布局的,contentInset 也是(0,0,0,0),怎么底部的內(nèi)容會(huì)被遮擋一部分呢?原因在于self.tableView = [[UITableView alloc] initWithFrame:self.view.bounds];初始化時(shí) rootView 的 frame 還是(0,0,screenWidth,screenHeight),只需要在viewWillLayoutSubviews中重新修改一下 tableview 的 frame 即可,


-(void)viewWillLayoutSubviews

{

[superviewWillLayoutSubviews];

_tableView.frame=self.view.bounds;

}

UINavigationBar 修改背景色

UINavigationBar是UIView的子類(lèi),首先想到的是修改背景色,

self.navigationController.navigationBar.backgroundColor = [UIColor greenColor];

發(fā)現(xiàn)這并不是我們想要的效果,為什么綠色變淡了呢?通過(guò) Xcode 的 ViewDebugging 我們可以看到UINavigationBar內(nèi)部還有一些子視圖,這些子視圖的背景色會(huì)遮擋住我們?cè)O(shè)置的顏色。

查看UINavigationBar的接口我們發(fā)現(xiàn)setBackgroundImage,設(shè)置

[self.navigationController.navigationBarsetBackgroundImage:[UIImageimageWithColor:[UIColorgreenColor]size:CGSizeMake(1,1)]forBarMetrics:UIBarMetricsDefault];

結(jié)果如下

小結(jié):設(shè)置UINavigationBar的 backgroundImage 可以修改導(dǎo)航欄的背景色。

translucent 和 setBackgroundImage

前面提到我們可以通過(guò)修改背景圖片來(lái)修改導(dǎo)航欄的背景色,設(shè)置了背景圖片后在有些頁(yè)面我們會(huì)遇到一些奇怪的問(wèn)題,發(fā)現(xiàn)原來(lái)布局正常的頁(yè)面顯示不對(duì)了,會(huì)多出一部分空白或者被導(dǎo)航欄遮擋住了。

通過(guò)打印出 translucent 的值我們發(fā)現(xiàn)設(shè)置了純色的背景圖后原來(lái)半透明的導(dǎo)航欄變成了不透明的,結(jié)合前面提到的 translucent 對(duì)布局起點(diǎn)的影響,如果頁(yè)面是按照半透明情況,即 rootView 從(0,0)開(kāi)始布局來(lái)設(shè)置子視圖的 frame,那么設(shè)置了純色背景圖后 translucent 變成了 false,即 rootView 從(0,64)開(kāi)始布局。為什么設(shè)置背景圖片會(huì)影響 translucent 呢,通過(guò)查看文檔發(fā)現(xiàn)了如下說(shuō)明,

/*

NewbehavioroniOS7.

DefaultisYES.

YoumayforceanopaquebackgroundbysettingthepropertytoNO.

Ifthenavigationbarhasacustombackgroundimage,thedefaultisinferred

fromthealphavaluesoftheimage—YESifithasanypixelwithalpha

也就是說(shuō)背景圖片如果包含 alpha 的色值,系統(tǒng)會(huì)默認(rèn)將 translucent 設(shè)置為 true,沒(méi)有包含 alpha 色值會(huì)將 translucent 設(shè)置為 false。這下真相大白了,原來(lái)我們前面設(shè)置了純綠色的背景圖片,是不包含 alpha 色值的,即系統(tǒng)默認(rèn)將 translucent 設(shè)置成了 false。但這是針對(duì)沒(méi)有手動(dòng)設(shè)置 translucent 值的情況,如果我們手動(dòng)設(shè)置了 translucent,那么系統(tǒng)就不會(huì)根據(jù)背景圖片的 alpha 來(lái)修改 translucent。

至此,我們了解了蘋(píng)果是如何使用這幾個(gè)屬性的,針對(duì) iOS7 以上,這里做一下總結(jié):

iOS7 以后 translucent 默認(rèn)為 true,rootView 從(0,0)開(kāi)始布局,修改 edgesForExtendedLayout 屬性可以改變布局;

translucent 為 false,rootView 從導(dǎo)航欄底部開(kāi)始布局,修改 edgesForExtendedLayout 屬性無(wú)法改變布局,可以通過(guò)設(shè)置 extendedLayoutIncludesOpaqueBars 從(0,0)開(kāi)始布局;

automaticallyAdjustsScrollViewInsets 默認(rèn)值是 true,表示在全屏模式下會(huì)自動(dòng)修改第一個(gè)添加到 rootView 的 scrollview 的 contentInset 為(64,0,0,0),用來(lái)糾正scrollview在全屏模式下的顯示;

設(shè)置UINavigationBar的背景圖片可以改變導(dǎo)航欄背景色,如果背景圖片包含 alpha 的色值,系統(tǒng)會(huì)默認(rèn)將 translucent 設(shè)置為 true,沒(méi)有包含 alpha 色值會(huì)將 translucent 設(shè)置為 false。但這是針對(duì)沒(méi)有手動(dòng)設(shè)置 translucent 值的情況,如果我們手動(dòng)設(shè)置了 translucent,那么系統(tǒng)就不會(huì)根據(jù)背景圖片的 alpha 來(lái)修改 translucent。

最后編輯于
?著作權(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)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • 最近項(xiàng)目里有個(gè)需求和導(dǎo)航欄的樣式定制有關(guān),深入之后發(fā)現(xiàn)之前理解的一些概念有些模糊,剛好趁著這次機(jī)會(huì)全面整理了一下。...
    hi_xgb閱讀 5,202評(píng)論 4 39
  • iOS 導(dǎo)航欄的屬性相關(guān) 轉(zhuǎn)載:http://www.open-open.com/lib/view/open148...
    張麒麟閱讀 295評(píng)論 0 0
  • *7月8日上午 N:Block :跟一個(gè)函數(shù)塊差不多,會(huì)對(duì)里面所有的內(nèi)容的引用計(jì)數(shù)+1,想要解決就用__block...
    炙冰閱讀 2,750評(píng)論 1 14
  • 就在五個(gè)人兩個(gè)名額里面,我都爭(zhēng)取不到。 我不知道,那五千塊錢(qián)對(duì)于我的意義。 只是,填表的時(shí)候太過(guò)粗糙。 機(jī)會(huì),弄掉...
    減肥的女孩閱讀 423評(píng)論 0 0
  • 伴隨著清晨的第一縷陽(yáng)光,清平學(xué)子走進(jìn)了學(xué)校?!袄蠋?,我撿到了一百塊錢(qián)。”清脆的聲音傳到執(zhí)勤牟老師耳朵里。她回頭一看...
    武際金閱讀 1,786評(píng)論 0 8

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