相關(guān)屬性標(biāo)簽:edgesForExtendedLayout,safeAreaInsets,translucent,automaticallyAdjustsScrollViewInsets,contentInset,adjustedContentInset,contentInsetAdjustmentBehavior
1.關(guān)于edgesForExtendedLayout 與 safeAreaInsets
1.1 edgesForExtendedLayout:iOS7推出,指定邊緣要延伸的方向,UIViewController屬性
默認(rèn)UIRectEdgeAll即self.view全屏顯示。
1.2 safeAreaInsets:iOS11推出,安全區(qū)域,view屬性
readonly只讀屬性,系統(tǒng)控制;同時(shí)新增兩個(gè)方法獲取安全區(qū)域改變
UIViewController中新增:
- (void)viewSafeAreaInsetsDidChange;
UIView中新增:
- (void)viewSafeAreaInsetsDidChange;
1.3 以下分別測(cè)試控制器view的frame,view的safeAreaInsets
iOS12.1下測(cè)試,以iPhone X(真機(jī),{375,812})為例
| edgesForExtendedLayout | view.frame(CGRect) | view.safeAreaInsets(UIEdgeInsets) |
|---|---|---|
| UIRectEdgeNone (帶導(dǎo)航欄) | {{0, 88}, {375, 724}} | {0, 0, 34, 0} |
| UIRectEdgeAll(帶導(dǎo)航欄) | {{0, 0}, {375, 812}} | {88, 0, 34, 0} |
| UIRectEdgeNone (不帶導(dǎo)航欄) | {{0, 0}, {375, 812}} | {44, 0, 34, 0} |
| UIRectEdgeAll(不帶導(dǎo)航欄) | {{0, 0}, {375, 812}} | {44, 0, 34, 0} |
iOS8.1和12.1下測(cè)試,以iPhone6(模擬器,{375,667})為例
| edgesForExtendedLayout | view.frame(CGRect) | view.safeAreaInsets(UIEdgeInsets) iOS8.1 | view.safeAreaInsets(UIEdgeInsets) iOS12.1 |
|---|---|---|---|
| UIRectEdgeNone (帶導(dǎo)航欄) | {{0, 64}, {375, 603}} | 沒(méi)有該屬性 | {0, 0, 0, 0} |
| UIRectEdgeAll(帶導(dǎo)航欄) | {{0, 0}, {375, 667}} | 沒(méi)有該屬性 | {64, 0, 0, 0} |
| UIRectEdgeNone (不帶導(dǎo)航欄) | {{0, 0}, {375, 667}} | 沒(méi)有該屬性 | {20, 0, 0, 0} |
| UIRectEdgeAll(不帶導(dǎo)航欄) | {{0, 0}, {375, 667}} | 沒(méi)有該屬性 | {20, 0, 0, 0} |
edgesForExtendedLayout值為其他情況時(shí)相信你已經(jīng)知道了,有興趣請(qǐng)自行測(cè)試。
總結(jié):edgesForExtendedLayout屬性影響在是否有NavigationBar,Tabbar時(shí)view的frame;safeAreaInsets屬性影響view的可視范圍的frame。
2.translucent:iOS3推出,半透明度,UINavigationBar屬性
Default is NO on iOS 6 and earlier. Always YES if barStyle is set to UIBarStyleBlackTranslucent
現(xiàn)在的App基本都支持iOS8.0以上,translucent可以認(rèn)為默認(rèn)為YES。translucent為YES,控制器view從坐標(biāo)(0,0)開(kāi)始;translucent為NO,控制器view從(0,64)開(kāi)始。當(dāng)我們使用滾動(dòng)視圖的時(shí)候,比如tableVIew,scrollview時(shí)候,建議不要修改translucent屬性,就是用系統(tǒng)默認(rèn)的YES
edgesForExtendedLayout = UIRectEdgeAll 時(shí)
iOS12.1下測(cè)試,以iPhone X(真機(jī),{375,812})為例
| view.frame(CGRect) | view.safeAreaInsets(UIEdgeInsets) | |
|---|---|---|
| translucent = NO (帶導(dǎo)航欄) | {{0, 88}, {375, 724}} | {0, 0, 34, 0} |
| translucent = YES (帶導(dǎo)航欄) | {{0, 0}, {375, 812}} | {88, 0, 34, 0} |
| translucent = NO(不帶導(dǎo)航欄) | {{0, 0}, {375, 812}} | {44, 0, 34, 0} |
| translucent = YES(不帶導(dǎo)航欄) | {{0, 0}, {375, 812}} | {44, 0, 34, 0} |
總結(jié):translucent = NO 與 edgesForExtendedLayout = UIRectEdgeNone效果相同。開(kāi)發(fā)中建議translucent = YES使用默認(rèn)值,在基類(lèi)中修改edgesForExtendedLayout = UIRectEdgeNone來(lái)控制所有控制器View的布局。
3.UIScrollView及其子類(lèi)
首先,根據(jù)以上的默認(rèn)屬性提出一個(gè)問(wèn)題:新建一個(gè)工程,讓初始的控制器(ViewController)帶導(dǎo)航欄,在ViewController的view上添加一個(gè)webview,webview的frame設(shè)置為self.view.frame。請(qǐng)問(wèn)webview的內(nèi)容會(huì)不會(huì)被導(dǎo)航欄擋???代碼理解如下:
有導(dǎo)航欄,translucent = YES 與 edgesForExtendedLayout = UIRectEdgeAll
- (void)viewDidLoad {
[super viewDidLoad];
WKWebView *webview = [[WKWebView alloc] init];
webview.frame = self.view.frame;
[self.view addSubview:webview];
[webview loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"https://www.baidu.com"]]];
}
接下來(lái)我們解決了解UIScrollView相關(guān)屬性
automaticallyAdjustsScrollViewInsets: 默認(rèn)YES,自動(dòng)適應(yīng)滾動(dòng)視圖的內(nèi)邊距,在iOS11系統(tǒng)后,該屬性無(wú)效。
scrollView.contentInset: 決定滾動(dòng)視圖的內(nèi)容和邊緣距離的屬性,iOS11由adjustedContentInset決定
adjustedContentInset: iOS11推出,readonly,When contentInsetAdjustmentBehavior allows, UIScrollView may incorporate its safeAreaInsets into the adjustedContentInset.(當(dāng)contentInsetAdjustmentBehavior允許時(shí),UIScrollView可以合并它的safeareainset進(jìn)入adjustedContentInset。)
contentInsetAdjustmentBehavior:內(nèi)邊距適應(yīng)行為,該值決定adjustedContentInset的值。
官方文檔:
typedef NS_ENUM(NSInteger, UIScrollViewContentInsetAdjustmentBehavior) {
UIScrollViewContentInsetAdjustmentAutomatic, // Similar to .scrollableAxes, but for backward compatibility will also adjust the top & bottom contentInset when the scroll view is owned by a view controller with automaticallyAdjustsScrollViewInsets = YES inside a navigation controller, regardless of whether the scroll view is scrollable
UIScrollViewContentInsetAdjustmentScrollableAxes, // Edges for scrollable axes are adjusted (i.e., contentSize.width/height > frame.size.width/height or alwaysBounceHorizontal/Vertical = YES)
UIScrollViewContentInsetAdjustmentNever, // contentInset is not adjusted
UIScrollViewContentInsetAdjustmentAlways, // contentInset is always adjusted by the scroll view's safeAreaInsets
} API_AVAILABLE(ios(11.0),tvos(11.0));
上述問(wèn)題的代碼在iPhone X,iOS12.1下測(cè)試
contentInsetAdjustmentBehavior 以下采用簡(jiǎn)寫(xiě):
| AdjustmentAutomatic | AdjustmentScrollableAxes | AdjustmentNever | AdjustmentAlways | |
|---|---|---|---|---|
| automaticallyAdjustsScrollViewInsets | YES | YES | YES | YES |
| contentInsetAdjustmentBehavior | 3 | 1 | 2 | 3 |
| scrollView.contentInset | {{0, 0}, {0, 0}} | {{0, 0}, {0, 0}} | {{0, 0}, {0, 0}} | {{0, 0}, {0, 0}} |
| self.view.safeAreaInsets | {88, 0, 34, 0} | {88, 0, 34, 0} | {88, 0, 34, 0} | {88, 0, 34, 0} |
| scrollView.adjustedContentInset | {88, 0, 34, 0} | {88, 0, 34, 0} | {0, 0, 0, 0} | {88, 0, 34, 0} |
測(cè)試打印:
po self.automaticallyAdjustsScrollViewInsets
po self.webview.scrollView.contentInsetAdjustmentBehavior
po NSStringFromUIEdgeInsets(self.webview.scrollView.contentInset)
po NSStringFromUIEdgeInsets(self.view.safeAreaInsets)
po NSStringFromUIEdgeInsets(self.webview.scrollView.adjustedContentInset)
總結(jié):UIScrollViewContentInsetAdjustmentAutomatic回去選擇一個(gè)最適合的適應(yīng)行為。UIScrollViewContentInsetAdjustmentNever就是adjustedContentInset = contentInsets;
UIScrollViewContentInsetAdjustmentAlways就是adjustedContentInset = safeAreaInsets + contentInsets;
UIScrollViewContentInsetAdjustmentScrollableAxes:它的成立依賴(lài)于滾動(dòng)軸,當(dāng)垂直方向上的contentSize大于滾動(dòng)視圖的高度時(shí),那么垂直方向上的 insets 就由`safeAreaInsets + contentInsets決定,水平方向上同理。
//豎屏狀態(tài)欄高度
#define Portrait_Status_SafeArea_Height (kDeviceInfo.isiPhoneXSeries ? 44 : 20)
//豎屏底部不帶tabbar安全區(qū)域高度
#define Portrait_Bottom_SafeArea_Height (kDeviceInfo.isiPhoneXSeries ? 34 : 0)
//豎屏底部帶tabbar時(shí)安全區(qū)域高度
#define Portrait_Tabbar_SafeArea_Height (kDeviceInfo.isiPhoneXSeries ? (49 + 34) : 49)
//橫屏底部安全區(qū)域的高度
#define Landscal_Bottom_SafeArea_Height (kDeviceInfo.isiPhoneXSeries ? 21 : 0)
//橫屏左右安全區(qū)域的寬度
#define Landscal_LeftRight_SafeArea_Width (kDeviceInfo.isiPhoneXSeries ? 44 : 49)
現(xiàn)在來(lái)回答最初提出的那個(gè)問(wèn)題:我們添加webview時(shí),使用的frame是self.view.frame,automaticallyAdjustsScrollViewInsets為默認(rèn)YES,在iOS12.1下測(cè)試,所以該屬性無(wú)效,contentInsetAdjustmentBehavior行為未設(shè)置,則默認(rèn)為Automatic即UIScrollViewContentInsetAdjustmentAlways,所以該webview的scrollView.adjustedContentInset為{88, 0, 34, 0},所以?xún)?nèi)容顯示是從導(dǎo)航欄底部開(kāi)始顯示的。