如何在UINavigationBar与UITabBar上方添加覆盖视图?添加到Window未果
我来帮你搞定这个问题!你直接把覆盖视图加到window上没成功,大概率是这两个原因:一是iOS 13+的多场景(Scene)机制导致你获取的window不对,二是约束设置没有让视图铺满整个window,或者层级没调整到最上层。下面是具体的解决步骤和代码示例:
1. 先获取正确的应用Window
iOS 13之后,[UIApplication sharedApplication].keyWindow已经不能可靠获取当前活跃的window了,因为一个App可能有多个场景。你需要遍历connectedScenes拿到当前前台活跃的window:
UIWindow *getCurrentWindow() { UIWindow *window = nil; if (@available(iOS 13.0, *)) { for (UIWindowScene *scene in [UIApplication sharedApplication].connectedScenes) { if (scene.activationState == UISceneActivationStateForegroundActive) { window = scene.windows.firstObject; break; } } } else { window = [UIApplication sharedApplication].keyWindow; } return window; }
2. 正确创建并添加覆盖视图
你之前的代码用了固定frame,这在不同尺寸的设备上会出问题,而且没有正确设置约束。下面是完整的showView方法,包含约束设置和层级调整:
- (void)showView { // 获取当前活跃的window UIWindow *currentWindow = getCurrentWindow(); if (!currentWindow) return; // 创建覆盖视图 UIView *animationOverlay = [[UIView alloc] init]; animationOverlay.translatesAutoresizingMaskIntoConstraints = NO; animationOverlay.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.6]; // 半透明背景,方便看到覆盖效果 animationOverlay.tag = 1001; // 加个tag,方便后续移除 // 创建按钮(补全你之前的代码) UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom]; btn.translatesAutoresizingMaskIntoConstraints = NO; [btn setTitle:@"关闭覆盖" forState:UIControlStateNormal]; [btn setBackgroundColor:[UIColor systemBlueColor]]; [btn addTarget:self action:@selector(hideOverlayView) forControlEvents:UIControlEventTouchUpInside]; // 添加到window [currentWindow addSubview:animationOverlay]; [animationOverlay addSubview:btn]; // 设置覆盖视图约束:铺满整个window [NSLayoutConstraint activateConstraints:@[ animationOverlay.topAnchor.constraintEqualToAnchor:currentWindow.topAnchor, animationOverlay.leadingAnchor.constraintEqualToAnchor:currentWindow.leadingAnchor, animationOverlay.trailingAnchor.constraintEqualToAnchor:currentWindow.trailingAnchor, animationOverlay.bottomAnchor.constraintEqualToAnchor:currentWindow.bottomAnchor ]]; // 设置按钮约束:居中显示,宽120高44 [NSLayoutConstraint activateConstraints:@[ btn.centerXAnchor.constraintEqualToAnchor:animationOverlay.centerXAnchor, btn.centerYAnchor.constraintEqualToAnchor:animationOverlay.centerYAnchor, btn.widthAnchor.constraintEqualToConstant:120, btn.heightAnchor.constraintEqualToConstant:44 ]]; // 确保覆盖视图在最上层(覆盖导航栏和tabBar) [currentWindow bringSubviewToFront:animationOverlay]; } // 移除覆盖视图的方法 - (void)hideOverlayView { UIWindow *currentWindow = getCurrentWindow(); UIView *overlay = [currentWindow viewWithTag:1001]; if (overlay) { [overlay removeFromSuperview]; } }
3. 额外注意事项
- 如果你不需要兼容iOS 13以下,也可以通过
UIApplication.sharedApplication.connectedScenes.firstObject来获取,但遍历判断活跃状态更稳妥。 - 确保
translatesAutoresizingMaskIntoConstraints设置为NO,否则AutoLayout约束不会生效,视图可能显示不出来。 - 如果你的App有自定义的window层级(比如某些第三方SDK添加的window),可能需要调用
[currentWindow bringSubviewToFront:animationOverlay]确保覆盖视图在最上层。
内容的提问来源于stack exchange,提问作者Shankar Naik
相关产品推荐
相关产品推荐

