最近在寫項目的時候,被UINavigationController以及NavigationBar的一個屬性給坑到了,折騰了挺久。這里整理一下,給后人提個醒。
導航控制器管理下的控制器,view的高度
在開發過程中,我們有時候可能會遇到這樣的情況:
UINavigationController管理下的控制器,其view的frame不是固定的。有時候是占據整個屏幕的,即CGRectMake(0,0,ScreenW,ScreenH)
。有時候又是從導航條底部開始的,即CGRectMake(0,64,ScreenW,ScreenH - 64)
那么這是為什么呢?又如何去解決這個問題,自定義view的尺寸和位置呢?
從iOS7開始,在UINavigationController管理下的控制器,其view的frame默認是:
CGRectMake(0,0,ScreenW,ScreenH)
也就是說占據整個屏幕。會被導航欄遮擋。
但是一些情況下,view的frame值會發生變化。
1. edgesForExtendedLayout
- 如果希望view的y值從64開始,而不是從0開始,可以設置控制器的
edgesForExtendedLayout
屬性。這個屬性的意思是,控制器的View是否需要向四個方向進行延伸。 - 這個屬性的默認值為
UIRectEdgeAll
,也就是向所有方向延伸,會被NavigationBar和TabBar給覆蓋住。 - 如果不希望延伸,可以在控制器的
viewDidLoad
方法中,將這個屬性修改為UIRectEdgeNone
。這樣,view的Y就是從64開始了,高度也會相應減少。
2. translucent
- 導航條有一個屬性
translucent
,表示NavigationBar是否半透明。默認是YES。 - 當這個值為YES時,那么控制器的view就可以延伸到導航條下方被覆蓋,也就是view的y從0開始。如果這個值為NO,那么控制器的view不會延伸到導航條下方,即使
edgesForExtendedLayout
屬性的值為UIRectEdgeAll
也不會延伸。 - 當給導航條設置了一個不透明(alpha = 1.0)的背景色時,那么這個值會被自動置為NO
- 所以如果給導航條設置了一個不透明的背景色,并且仍然希望控制器的View占據整個屏幕。那么需要設置一下導航條的translucent值
self.navigationController.navigationBar. translucent = YES;
3. extendedLayoutIncludesOpaqueBars
- 這是控制器的一個屬性,從字面意思可知,代表控制器的View是否需要延伸到半透明的Bar下面。
- 這個屬性的默認值為YES,也就是說當你的導航條或tabBar是半透明時(translucent為YES),view的frame會延伸到Bar下面,被遮擋。
- 如果想要在Bar為透明時也不延伸,可以將該屬性修改為NO。
4. automaticallyAdjustsScrollViewInsets
- 如果導航控制器下的控制器中有一個scrollView或者其子類,那么系統會自動將scrollView的
ContentInset
設置為UIEdgeMake(64,0,0,0)
,也就是增加了一個64的上方內邊距(只是修改了內邊距,但scrollView的frame仍然未被改變)。 - 有時候我們不想要這樣的自動內邊距,或者想要自定義內邊距,則可以在控制器的
viewDidLoad
方法中,將automaticallyAdjustsScrollViewInsets
屬性設置為NO即可
最后做一個總結
- 默認情況下,view是占據整個屏幕的。如果希望不占據整個屏幕,可以通過修改控制器的
edgesForExtendedLayout
實現。也可以通過修改控制器的extendedLayoutIncludesOpaqueBars
實現。 - 當給導航欄設置了一個不透明的背景色時,導航欄的
translucent
屬性會被置為NO,此時view在y方向的起點自動被調整為64。如果希望view的y值變回0,可以修改控制器的translucent
值為YES - 導航控制器管理下的控制器中的scrollView,會被自動設置64的上方內邊距。可以將
automaticallyAdjustsScrollViewInsets
置為NO來禁用這個自動設置。