天天看点

[iOS]Masonry适配SafeArea一、什么是SafeArea 二、针对safeAreaLayoutGuide布局三、Masonry关于safeArea的布局

一、什么是SafeArea

SafeArea:翻译中文语义即为安全区域,大家应该都不陌生,它是在iOS11引入的一个概念,在iPhoneX 等刘海屏出来之前,开发者如果想在一个ViewController的view上面添加子控件,只需要考虑我们想要添加的子控件距离屏幕上、下的边界。也就是在iOS7当中引入的两个属性:topLayoutGuide和bottomLayoutGuide。如果ViewController是被包裹在NavigationController或者SatusBar是可见的情况下,这两个属性就是分别表示子控件不被导航栏或状态栏挡住的区域。

在Apple发布了iPhoneX之后,针对横竖屏我们发现仅仅依靠上面两个属性是不能满足视图的布局的。在竖屏情况下,我们要针对上边的刘海和底部的Home Indicator做适配。在横屏的情况下我们要考虑左、右边(刘海)和底部(Home Indicator)的适配。苹果为了方便开发者做这方面的适配,特别针对UIView引入了safeAreaLayoutGuide属性。API对它的解释是:The layout guide representing the portion of your view that is unobscured by bars and other content.也就是说它是一个布局指南,这个布局指南使得我们对view的布局不受一些bar或者其他内容的遮挡。我们可以这么理解:所谓的安全区域就是safeAraeLayoutGuide这个虚拟的view所显示的区域,所有子控件只要是在这个虚拟的view之内都可以被完整的显示出来。

二、针对safeAreaLayoutGuide布局

我们考虑一下这个场景:在一个ViewController中的view上,我们想要放一个label,并且通过布局使之frame完全与view重合。在iOS11之前,我们写这个label的布局代码只需要针对这个view来写就可以了。但是现在情况可能不一样了,如果现在还是针对view来做的话,就会有可能导致我们添加的子控件的内容超出safeArea的范围。

下面,我们来看看在iOS11中是如何写布局的:

[self.view addSubview:self.lable];
    
self.lable.translatesAutoresizingMaskIntoConstraints = NO;
UILayoutGuide *safeGuide = self.view.safeAreaLayoutGuide;
NSLog(@"safeGuide.frame--->%@",NSStringFromCGRect(safeGuide.layoutFrame));
    
NSLayoutConstraint *topCon = [self.lable.topAnchor constraintEqualToAnchor:safeGuide.topAnchor];
NSLayoutConstraint *bottomCon = [self.lable.bottomAnchor constraintEqualToAnchor:safeGuide.bottomAnchor];
NSLayoutConstraint *leftCon = [self.lable.leftAnchor constraintEqualToAnchor:safeGuide.leftAnchor constant:0];
NSLayoutConstraint *rightCon = [self.lable.rightAnchor constraintEqualToAnchor:safeGuide.rightAnchor constant:0];
[NSLayoutConstraint activateConstraints:@[topCon, bottomCon, leftCon, rightCon]];
           

三、Masonry关于safeArea的布局

回到本文主题,我们看到如果用Apple的布局语法来写布局,很一件很费劲的事情(至少对于我来说是这样),代码冗长还可读性差。如果习惯了用Masonry布局的,就简单多了,这个库的作者专门针对safeArea也提供了相关的布局属性。具体的API大家有空上去看,带了mas_safeAreaLayout的都是作者封装好了的属性直接拿来用。目前可以通过这样来写达到上面那个例子的目的。

[self.view addSubview:self.label3];
if (@available(iOS 11,*)) {
    [self.label3 mas_makeConstraints:^(MASConstraintMaker *make) {
       make.top.mas_equalTo(self.view.mas_safeAreaLayoutGuideTop);
       make.left.equalTo(self.view.mas_safeAreaLayoutGuideLeft);
       make.right.equalTo(self.view.mas_safeAreaLayoutGuideRight);
       make.bottom.equalTo(self.view.mas_safeAreaLayoutGuideBottom);
    }];
 } else {
    make.edge.offset(0);
 }
           

使用Masonry有一个小技巧,我们平时在写控件布局的时候,不管是什么样的页面,我们都自定义一个ContentView,让这个ContentView针对safeAreaLayoutGuide做好布局,然后我们再在这个ContentView上写其他的子控件,这样做的好处的,不管控件多少或者多复杂,我们肯定能保证它们都可能完美显示。