You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI中实现fullScreenCover下层视图可交互的方法

纯SwiftUI实现全局顶层可交互动画视图

方法1:自定义可穿透的全屏覆盖(封装少量UIKit逻辑)

虽然用到了UIKit的窗口操作,但已封装为纯SwiftUI可用的组件,无需直接操作SceneDelegate:

  1. 创建全局状态管理器,控制动画视图的显示/隐藏
import SwiftUI

class GlobalOverlayManager: ObservableObject {
    @Published var showAnimatedView = false
    var animatedContent: AnyView?
}

// 将管理器注入SwiftUI环境
struct GlobalOverlayManagerKey: EnvironmentKey {
    static let defaultValue = GlobalOverlayManager()
}

extension EnvironmentValues {
    var globalOverlayManager: GlobalOverlayManager {
        get { self[GlobalOverlayManagerKey.self] }
        set { self[GlobalOverlayManagerKey.self] = newValue }
    }
}
  1. 封装顶层视图容器,自动将内容添加到系统最上层窗口
struct GlobalOverlayContainer: UIViewRepresentable {
    @Environment(\.globalOverlayManager) var manager
    
    func makeUIView(context: Context) -> UIView {
        let view = UIView()
        view.isUserInteractionEnabled = false // 允许点击穿透到下层内容
        DispatchQueue.main.async {
            updateOverlay(in: view)
        }
        return view
    }
    
    func updateUIView(_ uiView: UIView, context: Context) {
        updateOverlay(in: uiView)
    }
    
    private func updateOverlay(in uiView: UIView) {
        // 清理旧内容
        uiView.subviews.forEach { $0.removeFromSuperview() }
        
        guard manager.showAnimatedView, let content = manager.animatedContent else { return }
        
        // 包装SwiftUI视图为UIKit容器
        let hostingController = UIHostingController(rootView: content)
        hostingController.view.backgroundColor = .clear
        hostingController.view.isUserInteractionEnabled = false // 动画视图本身不拦截交互
        
        // 添加到最顶层窗口
        if let window = UIApplication.shared.windows.last {
            window.addSubview(hostingController.view)
            hostingController.view.frame = window.bounds
            
            // 自动隐藏动画(可根据需求调整时长)
            DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
                withAnimation {
                    manager.showAnimatedView = false
                }
            }
        }
    }
}
  1. 在App根视图中注入管理器并添加容器
@main
struct YourApp: App {
    @StateObject private var overlayManager = GlobalOverlayManager()
    
    var body: some Scene {
        WindowGroup {
            ContentView()
                .environment(\.globalOverlayManager, overlayManager)
                .background(GlobalOverlayContainer())
        }
    }
}
  1. 在任意视图中调用显示动画
struct ContentView: View {
    @Environment(\.globalOverlayManager) var overlayManager
    @State private var showSheet = false
    
    var body: some View {
        VStack(spacing: 20) {
            Button("显示顶层动画") {
                overlayManager.animatedContent = AnyView(
                    Text("我是顶层动画")
                        .font(.largeTitle)
                        .foregroundColor(.white)
                        .padding()
                        .background(.red)
                        .cornerRadius(10)
                )
                withAnimation {
                    overlayManager.showAnimatedView = true
                }
            }
            
            Button("弹出测试Sheet") {
                showSheet = true
            }
            .sheet(isPresented: $showSheet) {
                Text("这是一个Sheet")
                    .padding()
            }
        }
        .padding()
    }
}

方法2:修正fullScreenCover的交互问题(仅iOS 16+可用)

如果坚持使用fullScreenCover,可尝试以下修饰符组合(部分场景可能存在系统限制):

.fullScreenCover(isPresented: $showAnimatedView) {
    Text("顶层动画")
        .font(.largeTitle)
        .foregroundColor(.white)
        .padding()
        .background(.red)
        .cornerRadius(10)
        .background(.clear)
        .allowsHitTesting(false)
        .presentationBackground(.clear)
        .presentationBackgroundInteraction(.enabled)
        .presentationDetents([.large]) // 必须设置detent才能启用backgroundInteraction
}

注意:此方法受系统版本和场景限制,可靠性不如方法1。


内容的提问来源于stack exchange,提问作者Kudit

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 14:12:37