前言
之前的理解比较模糊,有些地方都理解错了,这次学习完整理下。
iOS 7以后的变化
iOS 7之后,UIViewController新增了三个属性来进行页面布局:
edgesForExtendedLayout (可延伸的边缘设置)
iOS 7之后默认开始使用全屏布局,作用于Controller的View,不论是嵌入到UINavigationController还是UITabbarController,根控制器Controller的View都会铺满整个屏幕,并且NavigationBar默认半透明,而edgesForExtendedLayout属性由UIRectEdge枚举赋值,默认是UIRectEdgeAll,效果如下:
可以看到self.view已经铺满了整个屏幕,红色部分已经浸入到NavigationBar和Tabbar,在self.view上添加子视图如果不想被遮挡,需要考虑NavigationBar和Tabbar的高度。
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);
注意下,此属性只作用于嵌入在容器中的控制器,其他地方不适用。
automaticallyAdjustsScrollViewInsets (自动适应滚动视图内边距?)
这个属性的作用于Controller的View上添加的ScrollView及其子类,通过控制ScrollView的contentInset值,让ScrollView包含的内容不会被Bar遮挡,默认为YES。
下面是默认为YES的情况:
可以看到虽然红色的TableView铺满了全屏,但是所包含的内容并没有被NavigationBar和TabBar所遮挡。
下面是为NO的情况:
可以看到TableView的内容已经被Bar挡住。
navigationBar.translucent (导航栏的透明度)
这个属性用于控制导航栏是否为半透明状态,默认为YES,同时他会影响到self.view的布局问题。当设置self.navigationController.navigationBar.translucent = NO时,self.view的布局并不会从顶部开始,而是从NavigationBar的底部开始。
这个时候再设置edgesForExtendedLayout = UIRectEdgeAll或者UIRectEdgeTop,都是没有作用的!也就是说,当设置导航栏不透明,根视图延伸的属性也起不到作用了。由此引出了extendedLayoutIncludesOpaqueBars。
extendedLayoutIncludesOpaqueBars (包括不透明Bars的延伸布局)
这个属性的作用是,当导航栏不透明的时候,self.view的布局要不要延伸到Bar的下面铺满屏幕,默认为NO。
但是!edgesForExtendedLayout会对这个属性有影响。
先设置
// 导航栏不透明
self.navigationController.navigationBar.translucent = NO;
// 布局延伸包括不透明导航栏
self.extendedLayoutIncludesOpaqueBars = YES;
如果
// self.view铺满屏幕
self.edgesForExtendedLayout = UIRectEdgeAll;
效果如下:
如果
// self.view不铺满屏幕
self.edgesForExtendedLayout = UIRectEdgeNone;
效果如下:
对以上四个属性的总结:
1:当导航栏半透明时(navigationBar.translucent = YES),self.view的布局只受edgesForExtendedLayout属性影响。
2:当导航栏不透明时(navigationBar.translucent = NO),self.view的布局受edgesForExtendedLayout和extendedLayoutIncludesOpaqueBars两个属性影响。
3:automaticallyAdjustsScrollViewInsets并不影响self.view的布局,只是当self.view添加ScrollView及其子类的时候,为了让包含的内容不被Bar遮住而调整contentInset的值。