如何实现SwiftUI中fullScreenCover的UIViewControllerRepresentable背景透明
问题原因
你在makeUIViewController中给ProfileCardViewController设置modalPresentationStyle = .overFullScreen不会生效,核心原因有两点:
- SwiftUI的
.fullScreenCover会自行管理外层展示容器,会覆盖被展示内容的modalPresentationStyle配置,默认强制使用.fullScreen样式——该样式下系统会主动移除下层视图的渲染,根本无法透出底层内容。 .fullScreenCover默认会在展示层级插入一个不透明的灰色背景层,即使你把内部UIViewController的视图设为透明,这层默认背景也会挡住下层内容。
修复方案
方案一:iOS 16及以上版本(最简实现)
不需要修改UIViewControllerRepresentable的现有代码,直接在.fullScreenCover的内容闭包中调用系统原生的透明背景修饰符即可:
.fullScreenCover(item: $userToPresent) { user in ProfileCardViewRepresentable(user: user) .ignoresSafeArea() .presentationBackground(.clear) }
该修饰符会自动将presentation样式切换为.overFullScreen,同时移除默认的不透明背景,直接透出下层SwiftUI视图内容。
方案二:兼容iOS 14~15低版本
如果需要支持iOS16以下系统,需要通过UIAdaptivePresentationControllerDelegate强制修改展示样式,同时手动移除SwiftUI插入的默认灰色背景:
- 首先修改
ProfileCardViewRepresentable实现,添加协调器处理presentation逻辑:
struct ProfileCardViewRepresentable: UIViewControllerRepresentable { let user: NPUserDataModel func makeCoordinator() -> Coordinator { Coordinator() } func makeUIViewController(context: Context) -> ProfileCardViewController { let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ProfileCardViewController") as! ProfileCardViewController vc.user = user vc.view.backgroundColor = .clear vc.presentationController?.delegate = context.coordinator return vc } func updateUIViewController(_ uiViewController: ProfileCardViewController, context: Context) {} class Coordinator: NSObject, UIAdaptivePresentationControllerDelegate { func adaptivePresentationStyle(for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle { return .overFullScreen } } }
- 添加辅助视图清除SwiftUI插入的默认背景,在fullScreenCover中调用:
// 辅助工具视图,用于清除presentation层级的默认不透明背景 struct ClearBackgroundView: UIViewRepresentable { func makeUIView(context: Context) -> UIView { let view = UIView() DispatchQueue.main.async { // 向上查找presentation容器层,将默认背景设为透明 if let containerView = view.superview?.superview { containerView.backgroundColor = .clear } } return view } func updateUIView(_ uiView: UIView, context: Context) {} } // 调用处代码 .fullScreenCover(item: $userToPresent) { user in ProfileCardViewRepresentable(user: user) .ignoresSafeArea() .background(ClearBackgroundView()) }
注意:如果
ProfileCardViewController的Storyboard中根视图本身设置了不透明背景色,需要手动将其修改为透明或者你需要的半透明效果,否则依然无法透出下层内容。
内容的提问来源于stack exchange,提问作者Sotiris Kaniras
相关产品推荐
相关产品推荐

