嵌入UINavigationController的VC弹出透明模态VC后背景变黑求助
问题原因分析
这个问题我之前也碰到过,核心根源出在UINavigationController默认的模态呈现样式上。当你的原视图控制器被嵌入导航控制器时,导航控制器默认的modalPresentationStyle是UIModalPresentationFullScreen——这种样式的设计逻辑是:模态弹出的控制器要完全覆盖底层内容,系统会在短暂延迟后自动把底层的UIWindow设为黑色,以此符合全屏模态的视觉规范。哪怕你把弹窗VC(pVC)的背景设为clear,导航控制器的呈现逻辑还是会触发这个窗口变暗的操作。
而当你测试两个独立的VC时,默认的呈现样式是UIModalPresentationAutomatic(iOS 13+),这种样式会自动适配透明背景的场景,所以不会出现窗口变黑的问题。
解决办法
只需要修改弹窗VC的模态呈现样式,让它适配透明背景的需求即可,有两种常用实现方式:
方式一:在弹窗VC内部设置
直接在pVC的viewDidLoad或者viewWillAppear方法里添加以下代码:
override func viewDidLoad() { super.viewDidLoad() // 设置模态呈现样式为覆盖全屏,保留底层内容 self.modalPresentationStyle = .overFullScreen // 确保背景透明生效 self.view.backgroundColor = .clear }
方式二:在原VC的segue准备阶段设置
如果是通过Storyboard的segue触发弹窗,可以在原VC的prepare(for:sender:)方法里提前配置目标VC的样式:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) { guard segue.identifier == "YourModalSegueID" else { return } guard let pVC = segue.destination as? YourPopupViewController else { return } pVC.modalPresentationStyle = .overFullScreen }
额外优化:支持点击外部关闭弹窗
如果你希望用户点击弹窗的透明区域(底层VC内容)就能关闭弹窗,可以给pVC的主视图添加点击手势:
// 在pVC的viewDidLoad里添加 let tapGesture = UITapGestureRecognizer(target: self, action: #selector(dismissPopup)) // 允许手势穿透到底层视图,不影响原VC的交互 tapGesture.cancelsTouchesInView = false self.view.addGestureRecognizer(tapGesture) // 实现关闭方法 @objc private func dismissPopup() { self.dismiss(animated: true) }
设置完overFullScreen样式后,再用视图层级调试器查看,UIWindow就不会再变黑了——因为系统不再认为这是一个需要完全覆盖底层内容的全屏模态,会保留原窗口的内容显示。
内容的提问来源于stack exchange,提问作者Tigran Iskandaryan
相关产品推荐
相关产品推荐

