项目中UITabBarController-UINavigationController-UIViewController 是这种层次结构:
自定义工具栏tabbar ,可以使用 UIViewController上的 additionalSafeAreaInsets属性来增加安全区的大小。
当使用这个层级结构时,一级页面-首页VC 有时需要隐藏或者展示tabbar
1. 设置UIViewController的属性 self.edgesForExtendedLayout = UIRectEdgeBottom; view 的布局可以穿透tabbar 全屏展示
通过 UIViewController的 additionalSafeAreaInsets属性,可以修改View的safeArea。
edgesForExtendedLayout 的枚举项:
UIRectEdgeNone = 0, navBar 底部与 tabBar 上部之间
UIRectEdgeTop = 1 << 0, navBar 上部与 tabBar 上部之间
UIRectEdgeLeft = 1 << 1,
UIRectEdgeBottom = 1 << 2, navBar 底部与 tabBar 底部之间
UIRectEdgeRight = 1 << 3,
UIRectEdgeAll = UIRectEdgeTop | UIRectEdgeLeft | UIRectEdgeBottom | UIRectEdgeRight
系统默认设置是UIRectEdgeAll。
参考文档:
edgesForExtendedLayout 的影响和效果
2 . 调整safeArea
通过修改safeArea,所有相对safeArea布局的UI都会跟着调整。
自定义的 Container ViewController,在底部增加一个工具栏bar,其 childViewController 的视图会tabbar挡住,可以调整childViewController的a dditionalSafeAreaInsets。
需要在 UIView 添加到视图层级中才会生效,应该写在 ContainerViewController 的 ViewDidAppear方法内
更改首页VC的SafeAreaInsets ,因为它是三层结构,需要在UITabBarController 的 viewDidAppear 方法中 添加以下代码:
注意点:
1. AdditionalSafeAreaInsets:controller可以扩展安全区域
当 view controller 的子视图覆盖了嵌入的子 view controller 的视图的时候。比如说, 当 UINavigationController 和 UITabbarController 中的 bar 是半透明(translucent) 状态的时候, 就有 additionalSafeAreaInsets。
viewController在iOS11中添加了一个新的属性additionalSafeAreaInsets, 通过该属性, 我们可以规定我们自己的safe ares insets, 最终系统根据我们设置的additionalSafeAreaInsets以及adjustedContentInset, 系统会计算出最终的 safe area.
注意: 如果viewController是在navigationController中, 那么应该先修改NavigationController 的 additionalSafeAreaInsets, 然后再改变viewController的additionalSafeAreaInsets.
例如:设置 self.additionalSafeAreaInsets = UIEdgeInsetsMake(20, 0, 0, 20); 意思就是在原有的safeAreaInsets值中增加对应的边距值。如果原来的是{10, 0, 0, 10}, 则最后得出的边距是{30, 0, 0, 30}。
if(@available(iOS11.0,*)){
self.additionalSafeAreaInsets = UIEdgeInsetsMake(-20,0,0,0);
} else{ // Fallback on earlier versions }
addtionalSafeAreaInset是Controller的属性,要知道SafeAreaInset的值是由哪个Controller引起的,可能是由UIViewController,可能是navigationController,也可能是UITabBarController。 所以当新建项目 只有一个VC的时候 直接在VC 设置就有效!
当新建项目 根视图是Nav,项目是 Nav+ VC的时候,直接在NavVC 设置才有效!
当新建项目 根视图是UITabBarController,项目是UITabBarController+多个Nav + VC的时候,在UITabBarController 中设置才有效!
2. -(void)viewSafeAreaInsetsDidChange:当视图的安全区域发生变更时会触发该方法,可以通过该方法来处理安全区域变更时的UI布局。
3. insetsLayoutMarginsFromSafeArea:默认值是YES,如果设置为NO,所有的视图布局将会忽略safeAreaInsets这个属性了。这个只对纯代码布局视图有效,如果是xib或者storyboard布局的话不起作用。一般用于tableView居多。
4. safeAreaInsets 和safeAreaLayoutGuide 属性只有在 viewSafeAreaInsetsDidChange() 方法时才生效.
更改additionalSafeAreaInsets属性后不是马上生效的,是在viewSafeAreaInsetsDidChange()方法时才生效。
当UIViewController 调用 viewDidLoad 时它的所有子视图的 safeAreaInsets 属性都等于 UIEdgeInsetsZero, 是无法通过当前视图控制器的子视图获取到 safeAreaInsets 的, 不过获取当前window对象的safeAreaInsets属性用来计算也是可以的, 但是不建议这么做, 一个视图控制器的子视图的处理当然要以它所在的控制器为准。
5. 控制器生命周期之viewSafeAreaInsetsDidChange 调用顺序
viewDidLoad
viewWillAppear
viewSafeAreaInsetsDidChange(NEW)
viewWillLayoutSubviews
viewDidAppear
viewSafeAreaInsetsDidChange 是在 viewWillAppear之后,viewWillLayoutSubviews之前被调用
6 :safeAreaLayoutGuide是UIView的属性,而topLayoutGuide和bottomLayoutGuide是UIViewController的属性。
参考文档:
additionalSafeAreaInsets 的使用,不正确设置无效果 多个层级的VC 时候需要在父containController 中设置才有效
苹果官方解说Auto Layout Techniques in Interface Builder
iOS中隐藏TabBar出现白条 -
关于 SafeArea 和 适配 iPhoneX -
纯代码搭建iOS三级结构(UITabbarController+UINavigationController+UIViewController)_ecjtuacm_yuewei的专栏-CSDN博客
iOS11适配-Safe Area - 灰信网(软件开发博客聚合)
iOS 11布局——SafeArea -
[译]iOS11安全区布局指南(Safe Area Layout Guide)
iOS开发-LayoutGuide(从top/bottom LayoutGuide到Safe Area) - 路人Q - 博客园
iOS11适配-Safe Area_WakeUpYQ-CSDN博客
iOS中safe area对scrollView的内容偏移产生的影响(iOS11的适配问题) -
iOS 11 additionalSafeAreaInsets的适用范围 - self.additionalSafeAreaInsets 的使用注意项,不然会无效!!!