與導航欄下控件的frame相關的edgesForExtendedLayout、translucent、extendedLayoutIncludesOpaqueBars、automaticallyAdjustsScrollViewInsets等幾個屬性的詳解


  在引入了導航控制器UINavigationController和分欄控制器UITabBarController之后,我們在設置控件的frame的時候就需要注意避開導航欄UINavigationBar 44+電源欄UIStatusBar 20的高度,和底部分欄UITabBar 44的高度。底部分欄並沒有太多需要處理的,我們只需要在計算高度的時候避開這44就可以了。而導航欄因為包含透明/半透明、第一個控件是否是UIScrollView或其子類等造成frame.origin.y的起點不同。我們現在來分析一下。

 

 

  1.edgesForExtendedLayout:UIRectEdge 擴展布局的邊緣

  在iOS7以后 UIViewController 開始使用全屏布局,而且是默認的屬性。通常涉及到布局,就離不開這個屬性 edgesForExtendedLayout,它是一個類型為UIExtendedEdge的屬性,指定UIViewController上的根視圖self.view邊緣要延伸的方向。由於iOS7鼓勵全屏布局,所以它的默認值是UIRectEdgeAll,四周邊緣均延伸,就是說,如果即使視圖中上有UINavigationBar,下有UITabBar,那么視圖仍會延伸覆蓋到四周的區域。

  (1)UIRectEdgeAll(Defalut)

                                圖1

  這里放置了一個frame為(0, 0, 100, 100)的view,backgroundColor設置為redColor,就是這個樣子。也就是說,此時的self.view是從屏幕頂到屏幕底的。此時我們計算控件frame的y的時候,如果想把控件在導航欄底部開始,那么y就是64。

  (2)UIRectEdgeNone

  因此,我們為了不讓我們的控件UIView延伸到UINavigationBar下面,我們可以將該屬性設置為UIRectEdgeNone。代碼如下:

 1   [self setEdgesForExtendedLayout:UIRectEdgeNone]; 

  ps:鑒於之前代碼OC與Swift都有,可能帶來的閱讀不習慣,以后貼代碼盡量使用OC,Swift獨有的那就沒辦法了。

                                圖2

  很清晰的可以看出來在設置為UIRectEdgeNone之后,self.view的是從導航欄底部到底部分欄頂部的。此時我們計算控件frame的y的時候,如果想把控件在導航欄底部開始,那么y就是0。

  (3)UIRectEdge

 1 typedef NS_OPTIONS(NSUInteger, UIRectEdge) {
 2 
 3     UIRectEdgeNone   = 0,
 4 
 5     UIRectEdgeTop    = 1 << 0,
 6 
 7     UIRectEdgeLeft   = 1 << 1,
 8 
 9     UIRectEdgeBottom = 1 << 2,
10 
11     UIRectEdgeRight  = 1 << 3,
12 
13     UIRectEdgeAll    = UIRectEdgeTop | UIRectEdgeLeft | UIRectEdgeBottom | UIRectEdgeRight  
14 
15 } NS_ENUM_AVAILABLE_IOS(7_0);

  很明顯,UIRectEdge是個枚舉類型。我們已經分析完了UIRectEdgeNone和UIRectEdgeAll,那么對UIRectEdgeTop和UIRectEdgeBottom也應該有所了解了。UIRectEdgeLeft/UIRectEdgeRight也不難猜測,就是對左右的擴展。目前沒有遇到過左右兩邊系統控件可能覆蓋掉自定義控件的情況,但遇到了我想大家也應該心里有數了吧。

 

 

  2.translucent:Bool 半透明的

  這個是self.navigationController.navigationBar的屬性,設置導航條UINavigationBar是否半透明。默認是YES,也就是半透明,看起來比較高大上,與圖1效果相同。

  當設置為不透明NO的時候,就涉及到下面第三條屬性了,不過在第三條默認的情況下,則被下壓,與圖2效果相同。

 1   [self.navigationController.navigationBar setTranslucent:NO]; 


          圖3

  圖中空出的部分,即為導航條UINavigationBar。此時計算frame應從導航欄下部為0開始計算,或者說控件會被下壓64。

  不過我們一般不會使用到這一條,因為半透明效果比較好看啊~

 

 

  3.extendedLayoutIncludesOpaqueBars:Bool 不透明的條下是否可以擴展

  很明顯,這條需要與上一條translucent搭配使用的,默認為NO,也就是不可以擴展。當translucent設置為NO,即導航欄UINavigationBar不透明的時候,默認不能擴展。若我們設置為YES,則會出現這種情況:

 

        圖4

  我並沒有改變紅色view的frame,而是被不透明的導航條蓋住看不到了。很明顯此時計算frame又是從屏幕最上方作為0開始計算了。

  為了計算究竟是在電源條下方還是屏幕最上方作為y的0點,改變了紅色view的height為64和65重復試驗,結果如下

      圖5:64開始

       圖6:65開始

  結論是從屏幕上方作為y的0開始計算。

  不過第2條都很少用,第3條使用的幾率...

 

 

  4.automaticallyAdjustsScrollViewInsets:Bool 自動校准滾動視圖的嵌入視圖

  這個其實就很簡單了,也是我們最常使用的一個吧。automaticallyAdjustsScrollViewInsets是一個bool類型,默認為YES,也就是會自動校准滾動視圖的嵌入視圖。不過這個只針對於UIScrollView及其子視圖,所以我們是用UITextView做一下測試。

  創建了一個frame為(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height)占據整個屏幕的UITextView,並放置了足夠多的文字。在默認automaticallyAdjustsScrollViewInsets為YES的前提下,我們測試下可能出現的結果。

 

            圖7 

  似乎什么毛病都沒有啊很正常啊。但是不要忘記我設置的frame的y是0啊。那大家可能就好奇了,難道UIScrollView的滾動視圖的frame是從導航欄下邊界算起的?

  不忙,我們設置automaticallyAdjustsScrollViewInsets為NO再試試。

 1   [self setAutomaticallyAdjustsScrollViewInsets:NO]; 

        圖8

  這個是一啟動就出現的界面,我並沒有向上滑動它的內容區域,也就是說,似乎此時的frame又是從屏幕下方開始的了。

  不要慌,我們改一下設置試試看。

  我將UITextView的frame設置為(0, 64, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height),也就是y改成了64;然后改變了它的背景顏色為紅色redColor;最后將[self setAutomaticallyAdjustsScrollViewInsets:NO];這行代碼注掉,讓它默認為YES。

  看一下效果。

            圖9

  注意:導航欄是半透明的,所以不存在被壓到紅色看不到的問題,也就是說,UITextView的frame的y的64的位置,是導航欄下方;那么0自然就是在屏幕下方開始計算了。

  很明顯,automaticallyAdjustsScrollViewInsets改變的並不是UIScrollView的frame,而是它的內容區域contentView的可滾動區域,也就是scrollIndicatorInsets。這是我們能滾到的最大范圍。相當於scrollIndicatorInsets這個屬性UIEdgeInsetsMake(<#CGFloat top#>, <#CGFloat left#>, <#CGFloat bottom#>, <#CGFloat right#>)的值從UIEdgeInsetsMake(0, 0, 0, 0)變為了UIEdgeInsetsMake(64, 0, 0, 0)。這就是automaticallyAdjustsScrollViewInsets這個屬性的作用。

  另外再說一點,這個automaticallyAdjustsScrollViewInsets的屬性,只對加在self.view上的第一個子視圖起作用,所以我們可以在將UIScrollView加載到self.view上之前先加載一個其他控件,這樣也能達到同樣的效果。

 1   [self.view addSubView:[[UIView alloc] init]]; 

 

  

  涉及導航欄下壓的情況大致就有這些,如遇到其他問題,會繼續補充。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



猜您在找 edgesForExtendedLayout,automaticallyAdjustsScrollViewInsets, extendedLayoutIncludesOpaqueBars的影響 iOS 導航欄translucent用法 淺析extendedLayout, automaticallyAdjustsScrollViewInsets, extendedLayoutIncludesOpaqueBars iOS中的translucent和automaticallyAdjustsScrollViewInsets用法 self.navigationController.navigationBar.translucent = YES航欄的屬性默認 YES是透明效果並且主view不會偏移 NO是導航欄不透明 主view會向下偏移64px iOS開發-automaticallyAdjustsScrollViewInsets屬性 iOS UITableviewWrapperView 和 automaticallyAdjustsScrollViewInsets屬性