原文地址:快速自動化適配iPhone X
關(guān)于iPhone X的適配擦剑,主要需要做的工作點就是針對上下非安全區(qū)域的適配控妻。
在iOS開發(fā)中,針對于布局存在 xib 與 代碼編輯 兩種方式妄呕。而這兩種方式又都支持 絕對布局 與 AutoLayout 兩種。
接下來本文將從xib捡多、代碼編輯蓖康、絕對布局铐炫、Autolayout幾個布局方式來講解如何針對iPhone X做自動化適配
Xib布局
Xib的絕對布局并不靈活,如果想要通過特有因素更改View的Frame則需要通過屬性索引來實現(xiàn)蒜焊。所以這里只針對Xib的AutoLayout來做講解
首先XCode9的Xib為我們提供了SafeAreaLayout選項倒信,而這個選項并不支持iOS9以前的版本。
SafeAreaLayout
那么我們需要針對靠近底部或者頂部非安全區(qū)域的View做約束就可以達到理想效果泳梆,然而約束的值卻不能固定鳖悠,你還需要兼顧非iPhone X的機型。
那么你可以從以下幾點中找到解決方法:
首先我們的布局文件如下:
三個相同的Label位于控制器根View的底部
約束文件
首先优妙,如果你是做一個新的頁面乘综,那么在設置約束時,添加Constrain to margins屬性會幫你大忙套硼,布局文件中的第二個Label就是使用Margin屬性進行布局卡辰。
Constrain to margins
首先,如果你有一個已經(jīng)存在的頁面邪意,而且已經(jīng)設置好了約束的布局九妈,那么你可以找到對應的約束屬性,勾選它的Relative to margin選項雾鬼,將此約束屬性以指向相對于marigin萌朱。
雙擊它 (╯>д<)╯?˙3˙?
約束屬性 Relative to margin入口
勾選它 (╯>д<)╯?˙3˙?
Relative to margin
接下來我們可以看到這三種布局產(chǎn)生的效果
你可以通過布局視圖左下角的View as: (某某機型) ,選擇iPhone X機型來快速查看布局應用結(jié)果策菜。
布局效果
以及運行的效果
運行效果
可以看到晶疼,基礎約束并不會對iPhone X底部的非安全區(qū)域進行適配酒贬,而Constrain to margins 與Relative to margin作用下的約束,則可以完美的適應iPhone X翠霍。
使用代碼布局
代碼布局依然可以通AutoLayout進行布局同衣,同時也可以通過分支判斷來進行絕對布局。
AutoLayout
1.如果你需要使用原生的API來進行AutoLayout布局壶运,那么你可以使用NSLayoutAttributeBottomMargin作為Bottom的約束枚舉值
NSLayoutConstraint?*constraint?=?[NSLayoutConstraint?constraintWithItem:self.leftLabel?>attribute:NSLayoutAttributeBottomMargin?relatedBy:NSLayoutRelationEqual?toItem:self.rightLabel?>attribute:NSLayoutAttributeBottom?multiplier:1constant:0];
[self.view?addConstraint:constraint];
2.如果你的Autolayout是通過Masonry進行編輯的耐齐,那么你只需要更改底部約束
在更早的Masonry版本中
由:
make.bottom.equalTo(self.view.mas_bottom);
改為:
make.bottom.equalTo(self.view.mas_bottomMargin);
[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時蒋情,通過:
由:
1make.bottom.equalTo(self.view.mas_bottom);
改為:
make.bottom.equalTo(self.view.mas_safeAreaLayoutGuideBottom);
[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(iOS11.0,?*))?{
make.bottom.equalTo(self.view.mas_safeAreaLayoutGuideBottom);
}else{
make.bottom.equalTo(self.view.mas_bottom);
}
}];
完整代碼如下
-?(void)viewDidLoad?{
[superviewDidLoad];
self.title?=?@"代碼布局";
[self?initSubViews];
[self?initLayout];
}
-?(void)initSubViews{
UILabel?*leftLabel?=?[[UILabel?alloc]?init];
leftLabel.text?=?@"基礎約束";
leftLabel.numberOfLines?=0;
leftLabel.textAlignment?=?NSTextAlignmentCenter;
leftLabel.backgroundColor?=?[UIColor?orangeColor];
UILabel?*rightLabel?=?[[UILabel?alloc]?init];
rightLabel.text?=?@"Constrain?to?margins";
rightLabel.numberOfLines?=0;
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(iOS11.0,?*))?{
make.bottom.equalTo(self.view.mas_safeAreaLayoutGuideBottom);
}else{
make.bottom.equalTo(self.view.mas_bottom);
}
}];
}
以及運行的效果
代碼布局
使用代碼布局
絕對布局
如果你需要使用代碼進行絕對布局埠况,那么iOS11中View的safeAreaInsets屬性可以幫到你。因為safeAreaInsets最低支持iOS11的緣故棵癣,所以你需要加入版本判斷來使用辕翰。safeAreaInsets會給出你上下左右各個方位的非安全區(qū)域的大小,你可以通過這些值來設置自己的View的位置狈谊。
1@property?(nonatomic,readonly)?UIEdgeInsets?safeAreaInsets?API_AVAILABLE(ios(11.0),tvos(11.0));
在這里我準備了幾個宏供大家使用
#define?IOS11_OR_LATER_SPACE(par)
({
float?space?=0.0;
if(@available(iOS11.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(0,?JF_KEY_WINDOW.safeAreaInsets.top-20))
#define?JF_BOTTOM_SPACE?IOS11_OR_LATER_SPACE(JF_KEY_WINDOW.safeAreaInsets.bottom)
宏里已經(jīng)進行了版本判斷喜命,如果你需要設置一個View置于控制器根View的底部,那么只需要通過
-?(void)createView{
UIView?*view?=?[[UIView?alloc]?initWithFrame:CGRectMake(0,0,100,100)];
view.backgroundColor?=?[UIColor?redColor];
[self.view?addSubview:view];
self.bottomView?=?view;
}
-?(void)viewDidLayoutSubviews{
[superviewDidLayoutSubviews];
CGRect?frame?=?self.bottomView.frame;
frame.origin.y?=?self.view.bounds.size.height?-?frame.size.height?-?JF_BOTTOM_SPACE;
self.bottomView.frame?=?frame;
}
以上代碼河劝,來減去非安全區(qū)的位置即可
PS:safeAreaInsets還可以用來進行設置連接于View邊緣的ScrollView的Insets額外滑動區(qū)域