iOS7之后的导航栏与控制器原点坐标问题
简单记录关于iOS7之后有导航控制器的控制器view原点坐标问题(view可能会被导航栏遮盖的问题)。
无UIScrollView的普通控制器的view
iOS7之前的属性wantsFullScreenLayout
已经被废弃,替代的是如下三个属性: UINavigationController的translucent
、UIViewController的edgesForExtendedLayout
和extendedLayoutIncludesOpaqueBars
,这个相信大家在实际项目开发中大多用过,这里做个简单的总结。
如果这三个属性使用默认值,view是撑满的,如下图:
如果要设置在导航栏下方开始你只要设置属性self.edgesForExtendedLayout = UIRectEdgeNone
(这里的枚举就不再赘述了,查看API就能知道), swift中是edgesForExtendedLayout = UIRectEdge(rawValue: 0)
,控制器的view的原点就会在导航栏的下方,如下图:
注: 只要设置了
edgesForExtendedLayout
属性 其他两个属性不管设置不设置效果都是一样的。
如果不设置edgesForExtendedLayout
属性怎么实现不撑满的效果呢?最简单的是设置UINavigationController的translucent
为NO, 这个时候控制器的原点就是从导航栏下方开始的,默认translucent
为YES,导航栏的半透明效果就是为了能看到这个效果才让view撑满屏幕,设置成NO就不需要此效果,原点就恢复到导航栏下方。
extendedLayoutIncludesOpaqueBars
此属性需要配合translucent
使用才会有效果,translucent
为YES的时候设置extendedLayoutIncludesOpaqueBars
是不会有作用的,只有当translucent
为NO的时候,设置extendedLayoutIncludesOpaqueBars
为YES时才会撑满,为NO时(默认)不撑满,具体看上面两张图。
那么有时候我需要控制器的view是撑满的效果,但是内部视图的布局是需要从导航栏下方开始的,这个时候就不要用frame来布局,用AutoLayout来布局就可以,这里用Masonry来布局,代码如下:
[topView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(30);
make.size.mas_equalTo(CGSizeMake(100, 80));
//不要用mas_top或者mas_centerY,相当于从左上角布局
make.top.equalTo(self.view.mas_topMargin).mas_offset(30);
// make.centerY.equalTo(self.view.mas_centerYWithinMargins);
}];
注: 最好布局采用AutoLayout,因为导航有侧滑手势,如果是不撑满的效果,侧滑时导航栏有渐变或者透明过渡的就比较难看
包含UIScrollView的控制器的view
包含UIScrollView及其子类的控制器的view设置的属性为automaticallyAdjustsScrollViewInsets
(iOS11之前API)、contentInsetAdjustmentBehavior
(iOS11及之后API).设置automaticallyAdjustsScrollViewInsets
为NO,设置contentInsetAdjustmentBehavior
为UIScrollViewContentInsetAdjustmentNever
即可。
注: 这里需要注意的是有多个UIScrollView及其子类的时候,一般上述设置只会对第一个产生效果,apple官方也建议多个UIScrollView及其子类的时候建议不用此属性设置,用AutoLayout布局去手动实现。