iOS7之後的導航欄與控制器原點座標問題
iOS7之後的導航欄與控制器原點座標問題
簡單記錄關於iOS7之後有導航控制器的控制器view原點座標問題(view可能會被導航欄遮蓋的問題)。
無UIScrollView的普通控制器的view
iOS7之前的屬性 wantsFullScreenLayout
已經被廢棄,替代的是如下三個屬性: UINavigationController的 translucent
、UIViewController的 edgesForExtendedLayout
和 extendedLayoutIncludesOpaqueBars
,這個相信大家在實際專案開發中大多用過,這裡做個簡單的總結。
如果這三個屬性使用預設值,view是撐滿的,如下圖:

撐滿
如果要設定在導航欄下方開始你只要設定屬性 self.edgesForExtendedLayout = UIRectEdgeNone
(這裡的列舉就不再贅述了,檢視API就能知道), swift中是 edgesForExtendedLayout = UIRectEdge(rawValue: 0)
,控制器的view的原點就會在導航欄的下方,如下圖:

在導航欄下方
注: 只要設定了 edgesForExtendedLayout
屬性 其他兩個屬性不管設定不設定效果都是一樣的。
如果不設定 edgesForExtendedLayout
屬性怎麼實現不撐滿的效果呢?最簡單的是設定UINavigationController的 translucent
為NO, 這個時候控制器的原點就是從導航欄下方開始的,預設 translucent
為YES,導航欄的半透明效果就是為了能看到這個效果才讓view撐滿螢幕,設定成NO就不需要此效果,原點就恢復到導航欄下方。
extendedLayoutIncludesOpaqueBars
此屬性需要配合 translucent
使用才會有效果, translucent
為YES的時候設定 extendedLayoutIncludesOpaqueBars
是不會有作用的,只有當 translucent
為NO的時候,設定 extendedLayoutIncludesOpaqueBars
為YES時才會撐滿,為NO時(預設)不撐滿,具體看上面兩張圖。
那麼有時候我需要控制器的view是撐滿的效果,但是內部檢視的佈局是需要從導航欄下方開始的,這個時候就不要用frame來佈局,用AutoLayout來佈局就可以,這裡用 Masonry 來佈局,程式碼如下:
[topView mas_makeConstraints:^(MASConstraintMaker *make) { make.left.mas_equalTo(30); make.size.mas_equalTo(CGSizeMake(100, 80)); //不要用mas_top或者mas_centerY,相當於從左上角佈局 make.top.equalTo(self.view.mas_topMargin).mas_offset(30); //make.centerY.equalTo(self.view.mas_centerYWithinMargins); }];
注: 最好佈局採用AutoLayout,因為導航有側滑手勢,如果是不撐滿的效果,側滑時導航欄有漸變或者透明過渡的就比較難看
包含UIScrollView的控制器的view
包含UIScrollView及其子類的控制器的view設定的屬性為 automaticallyAdjustsScrollViewInsets
(iOS11之前API)、 contentInsetAdjustmentBehavior
(iOS11及之後API).設定 automaticallyAdjustsScrollViewInsets
為NO,設定 contentInsetAdjustmentBehavior
為 UIScrollViewContentInsetAdjustmentNever
即可。
注: 這裡需要注意的是有多個UIScrollView及其子類的時候,一般上述設定只會對第一個產生效果,apple官方也建議多個UIScrollView及其子類的時候建議不用此屬性設定,用AutoLayout佈局去手動實現。