vc的几个影响view.frame的属性

1 普通viewController中edgesForExtendedLayout和Navibar的影响

iOS7开始, ViewController默认会使用全屏布局(full-screen layout). 并且在ViewController中增加了一些属性来影响VC管理的View的frame.

比如edgesForExtendedLayout, 它的值是UIExtendedEdge的属性,指定UIViewController上的根视图self.view边缘要延伸的方向,由于iOS7鼓励全屏布局,所以它的默认值是UIRectEdgeAll,四周边缘均延伸,就是说,如果即使视图中上有UINavigationBar,下有UITabBar,那么视图仍会延伸覆盖到四周的区域。它的文档说明如下枚举如下:

/*
Summary

The edges that you extend for your view controller.
Declaration

@property(nonatomic, assign) UIRectEdge edgesForExtendedLayout;
Discussion

Instead of this property, use the safe area of your view to determine which parts of your interface are occluded by other content. For more information, see the safeAreaLayoutGuide and safeAreaInsets properties of UIView.
In iOS 10 and earlier, use this property to report which edges of your view controller extend underneath navigation bars or other system-provided views. The default value of this property is UIRectEdgeAll, and it is recommended that you do not change that value.
If you remove an edge value from this property, the system does not lay out your content underneath other bars on that same edge. In addition, the system provides a default background so that translucent bars have an appropriate appearance. The window’s root view controller does not react to this property.
*/
typedef NS_OPTIONS(NSUInteger, UIRectEdge) {
    UIRectEdgeNone   = 0,
    UIRectEdgeTop    = 1 << 0,
    UIRectEdgeLeft   = 1 << 1,
    UIRectEdgeBottom = 1 << 2,
    UIRectEdgeRight  = 1 << 3,
    UIRectEdgeAll    = UIRectEdgeTop | UIRectEdgeLeft | UIRectEdgeBottom | UIRectEdgeRight
} API_AVAILABLE(ios(7.0));

默认情况下vc.edgesForExtendedLayout = UIRectEdgeAll, 它表示viewControllerview是从屏幕顶部最左上角开始布局!!!

当这个ViewController被嵌入到UINavigationControllerUITabBarController中时, 会受到NavgationControllerTabBarController的透明度(translucent)的影响!!!分成以下情况:

  • self.navigationController.navigationBar.translucent = YES;并且self.tabBarController.tabBar.translucent = YES; 那么vc.edgesForExtendedLayout = UIRectEdgeAll情况下, view依然会铺满全屏
  • self.navigationController.navigationBar.translucent = NO时, vc.view的左上角会从self.navigationController.navigationBar的左下角开始, 但是 self.view.frame == (0, 0, ScreenW, ScreenH - barHeight), 也就是从view从导航栏左下角那里开始布局!!! 同理 ``self.tabBarController.tabBar.translucent = NO;`类似

warning:

  1. 设置UINavigationBar.barStyle会影响到translucent 的属性!!! 一定要注意!!!!! 因此, 最好的方法是手动设置barStyle, 然后指定translucent的值!!!
  2. UIRectEdgeAll +navbar.translucent = NO , 在viewDidLoad方法中self.view.frame: NSRect: {{0, 0}, {375, 812}}, 而在viewDidLayoutSubviewsself.view.frame: NSRect: {{0, 0}, {375, 724}}

在iPhoneX中, 如果使用 UIRectEdgeNone配置, 那么不论self.navigationController.navigationBar.translucentYES或者NO, 在viewDidLoadself.view.frame: NSRect: {{0, 0}, {375, 812}}, 咋那么在viewDidLayoutSubviewsself.view.frame: NSRect: {{0, 88}, {375, 724}}会体现差别!!!请注意view.frame最终的originheight

automaticallyAdjustsScrollViewInsets

注意这个属性不会影响view.frame!!!!它会影响scrollview(self.view上第一个view)的contentInset!!!

当你的view是UIScrollerView或其子类(UITableView)时, 这个属性就派上用场了. 如果我们想让table从navbar的底部开始, 同事又希望滚动时, tbale延伸到整个view界面!!!(behind the navigation bar). 如果用edgesForExtendedLayout, 滚动时无法满足要求, 因为table始终从navigation bar的底部开始!!! 滚动时不会 behind it.

automaticallyAdjustsScrollViewInsets就能很好地满足需求,设置些属性值为YES(也是默认值),viewController会在table顶部添加inset,所以table的内容会出现在navigation bar的底部。但是滚动时又能覆盖整个屏幕(table.frame是全屏)

automaticallyAdjustsScrollViewInsets=NO时, 系统不会增加inset!!!

无论是YES or NO,滚支时table都是覆盖整个屏幕的,但是YES时,因为增加 inset的原因导致 table的内容不会被navigation bar挡住。

从苹果的官方文档可知,不只是navigation barstatus bar, search bar, toolbar or tab bar都有类似的效果, 也就是修改tableviewinset

extendedLayoutIncludesOpaqueBars

vc还有一个关键属性: extendedLayoutIncludesOpaqueBars, 表示不透明的bar下面是否可以扩展(default == NO, 也就是不扩展). 即导航栏UINavigationbar不透明的时, 默认不能扩展!!!

这个属性是对前面两个属性的补充!!! 如果navbar是不透明的, view不会被延伸到navbar底部!!!除非xtendedLayoutIncludesOpaqueBars = YES;

如果想要让你的view延伸到navigation bar(edgesForExtendedLayout to UIRectEdgeAll)并且设置此属性为NO(默认)。view就不会延伸到不透明的status bar。

其他总结

想要为UINavigationBar设置某个色值的纯色背景,则

  1. translucent属性为YES:
  • 如果想要通过视觉大大一丝不苟的像素眼,请参照https://www.jianshu.com/p/6a5552ec5099方案2:利用别的视图遮蔽掉这些透明控件
  • 否则若只是要求肉眼不容易发觉(请不要吐槽我的随便),请利用 barTintColor属性
  • 如果要求放松到无所谓的程度,透不透视都不关心,请使用 setBackgroundImage:forBarMetrics: 方法或者干脆用 backgroundColor属性
  1. translucent属性为NO:
  • 如果想要通过视觉大大一丝不苟的像素眼,依旧参照 https://www.jianshu.com/p/6a5552ec5099方案2:利用别的视图遮蔽掉这些透明控件
  • 否则若只是要求肉眼不容易发觉(请不要吐槽我的随便),使用barTintColor 或者 setBackgroundImage:forBarMetrics: 方法(仍然存在混色问题,例如设置纯红色,view hierarchy看单个视图取色为0xff0000,而直接从App中取色则前者效果为0xfb2930,后者效果为0xfc0d1b,相对而言后者更精准)

注意: backgroundColor 设置则是无效的,请放弃该方式

参考

https://www.jianshu.com/p/ca3c5a94c32b
https://www.cnblogs.com/helmsyy/p/8880835.html
https://www.jianshu.com/p/6a5552ec5099

你可能感兴趣的:(vc的几个影响view.frame的属性)