UINavigationController的导航栏的遮挡和透明
1.view被遮挡,默认被装入UINavigationController的子ViewController的view是全屏的,那么会导致子ViewController的view的上部会被UINavigationController的navigation bar 挡住。
2.UINavigationController的navigation bar的透明设置。
@interface BBViewController ()
@property (strong, nonatomic) UIView *subview;
@end
@implementation BBViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor redColor];
UIView *v = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 40)];
v.backgroundColor = [UIColor yellowColor];
[self.view addSubview:v];
self.subview = v;
}
@end
BBViewController *bv = [BBViewController new];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:bv];
nav.modalPresentationStyle = UIModalPresentationFullScreen;
[self presentViewController:nav animated:true completion:nil];
尝试解决遮挡问题:(在BBViewController中)
1.改变view的起点,使 view的起点在导航栏底部,不会被挡住。
方法一:
// 但是系统提供一个默认的背景色,使得半透明导航栏有适合的外观
self.edgesForExtendedLayout = UIRectEdgeNone;
// 一般不要使用
// 使用安全区域来代替,以确定界面的那些部分被其他内容挡住, safeAreaLayoutGuide, safeAreaInsets
方法二:
// 导航栏是白色
self.navigationController.navigationBar.translucent = NO;
此属性会被extendedLayoutIncludesOpaqueBars属性影响,如果extendedLayoutIncludesOpaqueBars的属性被设置为YES,则view的起点仍然是屏幕的起点,此属性默认是NO。
2.使用布局来限制子view的位置
方法一:使用NSLayoutConstraint和UILayoutGuide
v.translatesAutoresizingMaskIntoConstraints = NO;
UILayoutGuide *guide = self.view.safeAreaLayoutGuide;
[[v.topAnchor constraintEqualToAnchor:guide.topAnchor] setActive:YES];
[[v.leftAnchor constraintEqualToAnchor:guide.leftAnchor] setActive:YES];
[v addConstraint:[NSLayoutConstraint constraintWithItem:v attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeWidth multiplier:1.0 constant:200]];
[v addConstraint:[NSLayoutConstraint constraintWithItem:v attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeHeight multiplier:1.0 constant:40]];
方法二: 使用safeAreaInsets
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
// 由于UIView的safeAreaInsets只有在添加到视图层级后才生效,所以把布局代码写下viewDidLayoutSubviews方法中
UIEdgeInsets inset = self.view.safeAreaInsets;
CGFloat top = inset.top;
self.subview.frame = CGRectMake(0, top, 200, 40);
}
此方法会被ViewController的属性additionalSafeAreaInsets影响。
比如:
// 这个会将安全区域下移100
self.additionalSafeAreaInsets = UIEdgeInsetsMake(100, 0, 0, 0);
关于UINavigationController的navigation bar的透明
方法一:使用透明背景图,不推荐。
// 透明但是会残留一条线,view的起点是屏幕的起点
[self.navigationController.navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
方法二:使用隐藏,view的起点是屏幕的起点。
// 隐藏导航栏,对于view来说,就好像没有嵌入navigation controller栈中一样,edgesForExtendedLayout这个属性也无用
[self.navigationController.navigationBar setHidden:YES];
补充UI层次