如何让fullScreenCover上层的Sheet背景实现半透明?
解决FullScreenCover内Sheet背景半透明失效问题
问题原因
你之前的clearModalBackground方法仅通过view.superview?.superview固定层级清除背景,但在fullScreenCover内部弹出的Sheet,视图层级结构更复杂,系统的背景容器视图位置不在固定的两层父视图中,导致无法正确清除默认背景,因此材质效果无法显示。
修复方案
改进背景清除逻辑,通过递归遍历视图层级或关联的UIViewController来精准定位并清除系统默认背景:
方案一:递归遍历视图层级清除背景
修改ClearBackgroundView,递归查找并清除所有相关背景视图:
struct ClearBackgroundView: UIViewRepresentable { func makeUIView(context: Context) -> UIView { let view = UIView() DispatchQueue.main.async { func clearBackground(_ targetView: UIView?) { guard let currentView = targetView else { return } // 清除当前视图背景 if currentView.backgroundColor != .clear { currentView.backgroundColor = .clear } // 查找并清除系统内置的背景子视图(如_backgroundView) currentView.subviews.forEach { subview in if subview.description.contains("_backgroundView") { subview.backgroundColor = .clear } clearBackground(subview) } // 继续向上遍历父视图 clearBackground(currentView.superview) } clearBackground(view.superview) } return view } func updateUIView(_ uiView: UIView, context: Context) {} } struct ClearBackgroundViewModifier: ViewModifier { func body(content: Content) -> some View { content.background(ClearBackgroundView()) } } extension View { func clearModalBackground() -> some View { modifier(ClearBackgroundViewModifier()) } }
方案二:通过ViewController关联的PresentationController清除背景
利用UIView扩展查找所在的ViewController,直接操作PresentationController的容器视图:
struct ClearBackgroundView: UIViewRepresentable { func makeUIView(context: Context) -> UIView { let view = UIView() DispatchQueue.main.async { guard let viewController = view.findViewController() else { return } // 获取PresentationController并清除容器背景 if let presentationContainer = viewController.presentationController?.containerView { presentationContainer.backgroundColor = .clear // 清除容器内的系统背景子视图 presentationContainer.subviews.forEach { subview in if subview.description.contains("_backgroundView") { subview.backgroundColor = .clear } } } } return view } func updateUIView(_ uiView: UIView, context: Context) {} } // UIView扩展:查找所在的UIViewController extension UIView { func findViewController() -> UIViewController? { if let vc = next as? UIViewController { return vc } else if let parentView = next as? UIView { return parentView.findViewController() } return nil } } // 保持原有的Modifier和View扩展不变 struct ClearBackgroundViewModifier: ViewModifier { func body(content: Content) -> some View { content.background(ClearBackgroundView()) } } extension View { func clearModalBackground() -> some View { modifier(ClearBackgroundViewModifier()) } }
使用方式
保持原有调用逻辑不变即可:
StopDetail(coreStop: stop) .clearModalBackground() .background( Color.background.opacity(0.7) .ignoresSafeArea() .background(.ultraThinMaterial) )
这两种方案都能适配fullScreenCover内部弹出Sheet的场景,精准清除系统默认背景,让自定义的半透明材质背景正常显示。
内容的提问来源于stack exchange,提问作者David
相关产品推荐
相关产品推荐

