先声明:以下总结只对ios7及ios7之后才有效~~~
之前开发过程中偶尔会遇到设置导航栏透明与否或者运行系统版本号不一样出现控制器view或者tableview位置不正确的情况,虽然每次都能改回正确的布局,但是从来没有做过系统的总结,趁ios11、iphonex适配的过程中,做demo、查官方文档、查网上资料做了一篇总结,请多指教!!!
一、automaticallyAdjustsScrollViewInsets[iOS7.0-iOS11.0)
UIViewController的属性,表示是否需要 自适应可滚动视图的inserts。
如果是YES,表示会计算屏幕中被status bar、search bar、 navigation bar、toolbar等覆盖的区域,根据计算出来的区域 ,来自动填充可滚动视图的inserts;如果开发者自己设置了inserts或者frame,那么需要将此属性设置为NO,否则系统自适应和开发者自定义的双重作用,可能会导致不理想的布局。
二、edgesForExtendedLayout[7.0+]
UIViewController的属性,指定UIViewController上的根视图即self.view边缘要延伸的方向(即是否需要将viewcontroller.view延伸到status bar、navigation bar、tabbar等系统bar的下面)默认是UIRectEdgeAll
三、extendedLayoutIncludesOpaqueBars[iOS7.0+]
UIViewController的属性,表示在不透明bar(navigationBar、tabBar等)下 self.view是否可以延展,默认是NO,所以在bar透明情况下,此属性的设置不起作用。
四、UINavigationBar. translucent或者tabBar.translucent[iOS]
设置导航栏的透明度,ios7之后,导航栏默认是透明的,tabBar.translucent见下图解释
extendedLayoutIncludesOpaqueBars、navigationBar.translucent、edgesForExtendedLayout是控制控制器view的frame;
automaticallyAdjustsScrollViewInsets是设置可滚动视图的自适应偏移量;
这些属性并不是只设置一个就起作用的,需要相互作用,才能达到你想要的效果。
举例begin
extendedLayoutIncludesOpaqueBars、navigationBar.translucent、edgesForExtendedLayout属性联合设置对self.view的frame的影响举例如下:
{
self.navigationController.navigationBar.translucent = NO
self.extendedLayoutIncludesOpaqueBars = NO//默认就是NO
self.edgesForExtendedLayout = UIRectEdgeNone;//默认是UIRectEdgeAll
}
则self.view的起点是从导航栏左下角(0,64)开始
{
self.navigationController.navigationBar.translucent = NO
self.extendedLayoutIncludesOpaqueBars = YES//默认就是NO
self.edgesForExtendedLayout = UIRectEdgeAll;//默认是UIRectEdgeAll
}
则self.view的起点是从屏幕左上角(0,0)开始
{
self.navigationController.navigationBar.translucent = YES//默认是YES
self.edgesForExtendedLayout = UIRectEdgeNone;//默认是UIRectEdgeAll
}
则self.view的起点是从屏幕左上角(0,64)开始
{
self.navigationController.navigationBar.translucent = YES//默认是YES
self.edgesForExtendedLayout = UIRectEdgeAll;//默认是UIRectEdgeAll
}
则self.view的起点是从屏幕左上角(0,0)开始
extendedLayoutIncludesOpaqueBars、navigationBar.translucent、edgesForExtendedLayout结合automaticallyAdjustsScrollViewInsets对可滚动视图的布局影响:
{
[self.view addSubView:self.tableView];
self.tableView.frame = self.view.bounds;
self.navigationController.navigationBar.translucent = YES//默认是YES
self.edgesForExtendedLayout = UIRectEdgeAll;//默认是UIRectEdgeAll
self.automaticallyAdjustsScrollViewInsets = NO;//默认是YES
}
如下图所示,self.view的起点是从屏幕左上角(0,0)开始,tableview的起点也是从屏幕左上角(0,0)开始,tableiview开始从屏幕左上角显示内容,导致tableview顶部会被覆盖掉64像素。
{
[self.view addSubView:self.tableView];
self.tableView.frame = self.view.bounds;
self.navigationController.navigationBar.translucent = YES//默认是YES
self.edgesForExtendedLayout = UIRectEdgeAll;//默认是UIRectEdgeAll
self.automaticallyAdjustsScrollViewInsets = YES;//默认是YES
}
如下图所示,self.view的起点是从屏幕左上角(0,0)开始,tableview的起点也是从屏幕左上角(0,0)开始,但是tableview会从导航栏下面开始显示内容,所以tableivew能正常显示内容,没有被覆盖。
举例end
以上这些举例是为了让大家更好的理解各个属性的作用,及各个属性之间的相互作用!!!
五、contentInsetAdjustmentBehavior[iOS11+]
iOS11之后(包括iOS11)automaticallyAdjustsScrollViewInsets已经被废弃了,改为contentInsetAdjustmentBehavior作为可滚动视图的属性取代automaticallyAdjustsScrollViewInsets的作用。contentInsetAdjustmentBehavior结合其他属性(extendedLayoutIncludesOpaqueBars、navigationBar.translucent、edgesForExtendedLayout) 来控制可滚动视图能否正确显示在安全区域中。
提到contentInsetAdjustmentBehavior先要了解一下safeArea、safeAreaInsert、additionalSafeAreaInsets
1、safeArea:是ios11之后提出的安全区域,safeArea是指不被navbar、toolbar、tabbar、statusbar等覆盖的区域。
2、safeAreaInset(只可读):是UIView的属性,表示的是view距离该view安全区域的边距(或者理解为:插入多少方可使view能全部显示在安全区域中),只可读。
safeAreaInset,根据上图苹果官方文档解释可以得知:
当是视图控制器的根view时,safeAreaInset包括被bar覆盖部分和开发者设置的additiona insets
当是普通view时,如果当前视图在父视图的安全区域中,那么该视图的safeAreaInset 时 0,如果当前视图不在父视图的安全区域中 那么当前视图的safeAreaInset 等于被父视图的安全区域覆盖掉的部分(所以当前视图的safeAreaInset <=父视图的safeAreaInset)
以iphone8为例,则控制器view的safeAreaInsert为:
a、只有电池条:safeAreaInsert为(0,20,0,0)+
b、有电池条和导航栏:safeAreaInsert为(0,64,0,0)
c、有电池条、导航栏、tabBar safeAreaInsert为(64,0,49,0)
3、additionalSafeAreaInsets(可读写):控制器属性,开发者设置的额外的inserts
4、adjustContentInset(只可读):是系统计算出来的内容的填充insert,从苹果官方文档可以看出,adjustContentInset的值是由 contentInsetAdjustmentBehavior和contentinsert共同决定的。
contentInsetAdjustmentBehavior是个枚举类型 对应有四个value
a、UIScrollViewContentInsetAdjustmentAutomatic //adjustedContentInset = safeAreaInset + contentInset
b、UIScrollViewContentInsetAdjustmentScrollableAxes //在可滚动方向上,adjustedContentInset = safeAreaInset + contentInset,在不可滚动方向上:adjustedContentInset = contentInset
c、UIScrollViewContentInsetAdjustmentNever //adjustedContentInset = contentInset
d、UIScrollViewContentInsetAdjustmentAlways //adjustedContentInset = safeAreaInset + contentInset
adjustContentInset决定了可滚动视图的偏移量,而adjustContentInset是由ontentInsetAdjustmentBehavior和contentinsert 共同决定的,而contentinsert是用户自定义可知的,所以最具有决定性影响的就是contentInsetAdjustmentBehavior的取值了。
举例begin
{
self.tableView.frame = self.view.bounds;
self.edgesForExtendedLayout = UIRectEdgeAll;
self.extendedLayoutIncludesOpaqueBars = YES
self.navigationController.navigationBar.translucent = NO
self.tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
}
UIScrollViewContentInsetAdjustmentNever试系统没有自适应被覆盖的部分,所以tableview会被bar给遮挡,如下图导航栏下面的黄色就是tableview被遮挡的部分
{
self.tableView.frame = self.view.bounds;
self.edgesForExtendedLayout = UIRectEdgeAll;
self.extendedLayoutIncludesOpaqueBars = YES
self.navigationController.navigationBar.translucent = NO
self.tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentAutomatic;
}
虽然起点依然是从屏幕左上角(0,0)开始的,但是UIScrollViewContentInsetAdjustmentAutomatic会自动填充被遮挡的部分,所以tableview会全部显示在安全区域中,如下图所示黄色区域没有被遮挡
举例end
希望这篇文章能帮到你,当然如果看了这篇文章你或者他(她)认为有什么不对的地方 或者 有更高的见解,欢迎讨论~~~
如果需要demo的话,后期我会把demo上传到csdn,发链接出来供大家参考!!!
参考资料:
http://www.jianshu.com/p/efbc8619d56b
https://developer.apple.com/library/content/navigation/#section=Resource%20Types&topic=Reference