iOS 9/10 safeArea 适配
iOS11出来已经近一年了,适配也基本上搞的差不多了,我们都知道iOS11后才有的安全区概念,但是在iOS10及以下没有这个概念,虽然以前的项目适配的差不多了,不过新项目中发现一个我一直没有发现的适配问题,现将问题记录下来,以便以后查看。
说明:界面是通过Xib+AutoLayout搭建的。
场景1 - UIViewController中含有顶部导航
-
应用场景描述
图1.png
如图,我们想要让输入框顶部距离导航栏底部为10
图2.png -
视图层次结构
图中,控制器view
中有一个子view
作为backgroundView
,backgroundView
中有一个输入框nameTextField
,nameTextField
距离父视图backgroundView
左右为15,上下为0。 -
解决办法
我们可以在图2中看到,顶部的约束采用了安全区概念,我们都知道从iOS7开始,苹果就采用一种全屏布局(full-screen)的概念,说白了,就是我们日常看到的,顶部导航,和底部TabBar半透明状态下,视图的背景色可以渗透到顶部导航和底部TabBar,给人一种更舒服的视觉效果。说到全屏布局,我们可能就想到了@property(nonatomic,assign) UIRectEdge edgesForExtendedLayout NS_AVAILABLE_IOS(7_0); // Defaults to UIRectEdgeAll
,
这个属性,默认是全屏布局,我们再来看一下UIRectEdge
:
typedef NS_OPTIONS(NSUInteger, UIRectEdge) {
UIRectEdgeNone = 0,
UIRectEdgeTop = 1 << 0,
UIRectEdgeLeft = 1 << 1,
UIRectEdgeBottom = 1 << 2,
UIRectEdgeRight = 1 << 3,
UIRectEdgeAll = UIRectEdgeTop | UIRectEdgeLeft | UIRectEdgeBottom | UIRectEdgeRight
} NS_ENUM_AVAILABLE_IOS(7_0);
到这我想大家都明白了,我们现在如果不想让controller.view
延展到navigationBar
下面,我们可以在controller
中将edgesForExtendedLayout
设置为UIRectEdgeNone
(ps:如果不太了解edgesForExtendedLayout
这个属性,可搜索之深入了解一下,这里不再做详细讲述):
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
self.edgesForExtendedLayout = UIRectEdgeNone;
}
到此完美解决第一个问题。
场景2 - UIViewController中不含有顶部导航
-
应用场景
图3.png
从图3中我们可以看到,登录界面是右上角有个关闭按钮“X”,整个界面是通过present出来的,顶部是没有导航栏的。我们的需求是关闭按钮距离状态栏顶部距离为64。
-
视图层次结构
我们知道在iPhone X中,状态栏的高度由20高变成了44高,所以,在iPhone X下,我们的关闭按钮距离顶部安全区的距离应该设置为20,但是在除iPhone X以外的手机,在没有刘海的情况下,就会出现关闭按钮紧紧贴着状态栏的情况。如图4
图4.png -
解决办法
知道了原因,想要找到解决办法也是很简单,多添加一个距离顶部为64的约束,并把约束优先级调整为1000以下,程序会优先满足优先级高的约束,如图5,图6所示:
图5.png
图6.png
到此,大功告成!