导航栏布局几个老生常谈的问题
1.edgesForExtendedLayout
、automaticallyAdjustsScrollViewInsets
和extendedLayoutIncludesOpaqueBars
这三个属性适用于iOS 11以前对布局的调整
①edgesForExtendedLayout
:当在UINavigationController内添加UIViewController的时候,用来控制UIViewController中的view的大小。当你将UIViewController的该值设置为UIRectEdgeAll
(默认值)的时候,UIViewController会延伸至UINavigationBar以下铺满整个屏幕,效果如下图(红色半透明效果是导航栏设置导致的):
②automaticallyAdjustsScrollViewInsets
:当UIViewController的view
或者view的第一个子View
是UIScrollView及其子类的时候,有时候我们希望视图可以滚动到导航栏以下的区域,但是如果只是单纯的把edgesForExtendedLayout
设置为UIRectEdgeAll
的话视图最开始会有部分内容被盖在导航栏以下,将automaticallyAdjustsScrollViewInsets
设置为YES
(默认值)则会自动帮你调整视图的Insets使内容刚好从导航栏底下开始,如下图所示(此时edgesForExtendedLayout
为UIRectEdgeAll
, 列表铺满整个屏幕):
③extendedLayoutIncludesOpaqueBars
:当你将导航栏或者状态栏设为不透明的时候,你会发现即使将edgesForExtendedLayout
设置为UIRectEdgeAll
,view也不会扩充到导航栏或者状态栏下去,这是因为extendedLayoutIncludesOpaqueBars
的默认值是NO。当将其改为YES的时候就可以实现延伸效果了。
2.additionalSafeAreaInsets
和UIScrollVIew及其子类的contentInsetAdjustmentBehavior
以上是基于iOS11的safeAreaInsets
出现而出现的调整布局的API
①additionalSafeAreaInsets
:如果你想在默认的safeAreaInset
的基础上对当前的UIViewController的safeAreaInsets
做一些额外的调整,那就可以使用这个属性。举个例子,如果系统当前的safeAreaInsets
是(top: 88.0, left: 0.0, bottom: 34.0, right: 0.0)
,并且你将additionalSafeAreaInsets
设置为(top:5, left:5, bottom:5, right:5)
,那么最后的safeAreaInsets
就会变成(top: 93.0, left: 5.0, bottom: 39.0, right: 5.0)
。由此引申的一个问题就是永远
在viewSafeAreaInsetsDidChange
这个回调里取获取safeAreaInset
,再对视图做调整。
②contentInsetAdjustmentBehavior
:在iOS 11之后automaticallyAdjustsScrollViewInsets
失效,将其设置为UIScrollViewContentInsetAdjustmentNever
与automaticallyAdjustsScrollViewInsets
设置为NO同效,即不做任何调整(一般在基类写布局的时候会这么做)。针对其他的几个值,其中UIScrollViewContentInsetAdjustmentScrollableAxes
表示如果某个方向可滚动(分为contentSize的宽或者高大于该视图宽或者高以及alwaysBounceXXX设为YES这两种情况),则其该方向的Inset将被设置为safeAreaInset的值,使可滚动方向的内容拥有足够的展示空间。UIScrollViewContentInsetAdjustmentAlways
则不管可不可以滚动都预留safeAreaInset的Inset空间出来。UIScrollViewContentInsetAdjustmentAutomatic
比较特殊,它在大部分情况下和UIScrollViewContentInsetAdjustmentScrollableAxes
一致,但是当:
- UIScrollView 类型的视图在水平轴方向是可滚动的,垂直轴是不可滚动的。
- ViewController 视图里的第一个子控件是 UIScrollView 类型的视图。
- ViewController 是 navigation 或者 tab 类型控制器的子视图控制器。
- automaticallyAdjustsScrollViewInsets = YES
的时候,它等于UIScrollViewContentInsetAdjustmentAlways
。
3