天天看點

快速自動化适配iPhone X

轉自:http://www.code4app.com/blog-822717-1471.html

關于iPhone X的适配,主要需要做的工作點就是針對上下非安全區域的适配。

在iOS開發中,針對于布局存在 xib 與 代碼編輯 兩種方式。而這兩種方式又都支援 絕對布局 與 AutoLayout 兩種。

快速自動化适配iPhone X

接下來本文将從xib、代碼編輯、絕對布局、Autolayout幾個布局方式來講解如何針對iPhone X做自動化适配

  • Xib布局

Xib的絕對布局并不靈活,如果想要通過特有因素更改View的Frame則需要通過屬性索引來實作。是以這裡隻針對Xib的AutoLayout來做講解

首先XCode9的Xib為我們提供了SafeAreaLayout選項,而這個選項并不支援iOS9以前的版本。

快速自動化适配iPhone X

SafeAreaLayout

那麼我們需要針對靠近底部或者頂部非安全區域的View做限制就可以達到理想效果,然而限制的值卻不能固定,你還需要兼顧非iPhone X的機型。

那麼你可以從以下幾點中找到解決方法:

首先我們的布局檔案如下:

  • 三個相同的Label位于控制器根View的底部
快速自動化适配iPhone X

限制檔案

首先,如果你是做一個新的頁面,那麼在設定限制時,添加Constrain to margins屬性會幫你大忙,布局檔案中的第二個Label就是使用Margin屬性進行布局。

快速自動化适配iPhone X

Constrain to margins

首先,如果你有一個已經存在的頁面,而且已經設定好了限制的布局,那麼你可以找到對應的限制屬性,勾選它的Relative to margin選項,将此限制屬性以指向相對于marigin。

  • 輕按兩下它 (╯>д<)╯⁽˙³˙⁾
快速自動化适配iPhone X

限制屬性 Relative to margin入口

  • 勾選它 (╯>д<)╯⁽˙³˙⁾
快速自動化适配iPhone X

Relative to margin

  • 接下來我們可以看到這三種布局産生的效果
  • 你可以通過布局視圖左下角的View as: (某某機型) ,選擇iPhone X機型來快速檢視布局應用結果。
快速自動化适配iPhone X

布局效果

  • 以及運作的效果
快速自動化适配iPhone X

運作效果

  • 可以看到,基礎限制并不會對iPhone X底部的非安全區域進行适配,而Constrain to margins 與Relative to margin作用下的限制,則可以完美的适應iPhone X。
  • 使用代碼布局

代碼布局依然可以通AutoLayout進行布局,同時也可以通過分支判斷來進行絕對布局。

  • AutoLayout

1.如果你需要使用原生的API來進行AutoLayout布局,那麼你可以使用NSLayoutAttributeBottomMargin作為Bottom的限制枚舉值

1 2

NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:self.leftLabel >attribute:NSLayoutAttributeBottomMargin relatedBy:NSLayoutRelationEqual toItem:self.rightLabel >attribute:NSLayoutAttributeBottom multiplier:

1

constant:

];

[self.view addConstraint:constraint];

2.如果你的Autolayout是通過Masonry進行編輯的,那麼你隻需要更改底部限制

  • 在更早的Masonry版本中

由:

1

make.bottom.equalTo(self.view.mas_bottom);

改為:

1

make.bottom.equalTo(self.view.mas_bottomMargin);

1 2 3 4 5 6

[self.rightLabel mas_makeConstraints:^(MASConstraintMaker *make) {

make.height.mas_equalTo(

100

);

make.left.equalTo(self.leftLabel.mas_right);

make.right.equalTo(self.view);

make.bottom.equalTo(self.view.mas_bottomMargin);

}];

  • 在新的Masonry版本中,當編譯器提醒你找不到mas_bottomMargin時,通過:

由:

1

make.bottom.equalTo(self.view.mas_bottom);

改為:

1

make.bottom.equalTo(self.view.mas_safeAreaLayoutGuideBottom);

1 2 3 4 5 6 7 8 9 10

[self.rightLabel mas_makeConstraints:^(MASConstraintMaker *make) {

make.height.mas_equalTo(

100

);

make.left.equalTo(self.leftLabel.mas_right);

make.right.equalTo(self.view);

if

(@available(iOS 

11.0

, *)) {

make.bottom.equalTo(self.view.mas_safeAreaLayoutGuideBottom);

else

{

make.bottom.equalTo(self.view.mas_bottom);

}

}];

  • 完整代碼如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45

- (

void

)viewDidLoad {

[

super

viewDidLoad];

self.title = @

"代碼布局"

;

[self initSubViews];

[self initLayout];

}

- (

void

)initSubViews{

UILabel *leftLabel = [[UILabel alloc] init];

leftLabel.text = @

"基礎限制"

;

leftLabel.numberOfLines = 

;

leftLabel.textAlignment = NSTextAlignmentCenter;

leftLabel.backgroundColor = [UIColor orangeColor];

UILabel *rightLabel = [[UILabel alloc] init];

rightLabel.text = @

"Constrain to margins"

;

rightLabel.numberOfLines = 

;

rightLabel.textAlignment = NSTextAlignmentCenter;

rightLabel.backgroundColor = [UIColor blueColor];

[self.view addSubview:leftLabel];

[self.view addSubview:rightLabel];

self.leftLabel = leftLabel;

self.rightLabel = rightLabel;

}

- (

void

)initLayout{

[self.leftLabel mas_makeConstraints:^(MASConstraintMaker *make) {

make.height.mas_equalTo(

100

);

make.width.equalTo(self.view).multipliedBy(

0.5

);

make.left.equalTo(self.view);

make.bottom.equalTo(self.view.mas_bottom);

}];

[self.rightLabel mas_makeConstraints:^(MASConstraintMaker *make) {

make.height.mas_equalTo(

100

);

make.left.equalTo(self.leftLabel.mas_right);

make.right.equalTo(self.view);

if

(@available(iOS 

11.0

, *)) {

make.bottom.equalTo(self.view.mas_safeAreaLayoutGuideBottom);

else

{

make.bottom.equalTo(self.view.mas_bottom);

}

}];

}

  • 以及運作的效果
快速自動化适配iPhone X

代碼布局

  • 使用代碼布局
  • 絕對布局
如果你需要使用代碼進行絕對布局,那麼iOS11中View的safeAreaInsets屬性可以幫到你。因為safeAreaInsets最低支援iOS11的緣故,是以你需要加入版本判斷來使用。safeAreaInsets會給出你上下左右各個方位的非安全區域的大小,你可以通過這些值來設定自己的View的位置。
1

@property (nonatomic,readonly) UIEdgeInsets safeAreaInsets API_AVAILABLE(ios(

11.0

),tvos(

11.0

));

  • 在這裡我準備了幾個宏供大家使用
1 2 3 4 5 6 7 8 9 10 11

#define IOS11_OR_LATER_SPACE(par) 

({

float space = 

0.0

;

if

(@available(iOS 

11.0

, *))

space = par;

(space);

})

#define JF_KEY_WINDOW [UIApplication sharedApplication].keyWindow

#define JF_TOP_SPACE IOS11_OR_LATER_SPACE(JF_KEY_WINDOW.safeAreaInsets.top)

#define JF_TOP_ACTIVE_SPACE IOS11_OR_LATER_SPACE(MAX(

, JF_KEY_WINDOW.safeAreaInsets.top-

20

))

#define JF_BOTTOM_SPACE IOS11_OR_LATER_SPACE(JF_KEY_WINDOW.safeAreaInsets.bottom)

  • 宏裡已經進行了版本判斷,如果你需要設定一個View置于控制器根View的底部,那麼隻需要通過
1 2 3 4 5 6 7 8 9 10 11 12 13 14

- (

void

)createView{

UIView *view = [[UIView alloc] initWithFrame:CGRectMake(

100

100

)];

view.backgroundColor = [UIColor redColor];

[self.view addSubview:view];

self.bottomView = view;

}

- (

void

)viewDidLayoutSubviews{

[

super

viewDidLayoutSubviews];

CGRect frame = self.bottomView.frame;

frame.origin.y = self.view.bounds.size.height - frame.size.height - JF_BOTTOM_SPACE;

self.bottomView.frame = frame;

}

以上代碼,來減去非安全區的位置即可

PS:safeAreaInsets還可以用來進行設定連接配接于View邊緣的ScrollView的Insets額外滑動區域

Demo下載下傳: https://github.com/Jiang-Fallen/LayoutiPhoneX