简单记录关于 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 布局去手动实现.
来源: http://www.jianshu.com/p/393c69f082b1