有没有办法设置 fullScreenCover 背景不透明度?

Asw*_*ath 3 ios swiftui

我需要从视图组件内的按钮推送一个模态视图,但应该只覆盖屏幕高度的下半部分,上半部分是半透明背景(黑色,不透明度为 30%)。在 fullscreenCover 视图构建器中设置最顶层视图的不透明度不起作用。任何帮助,将不胜感激。

struct ContentView: View {
    
    @State var present: Bool = false
    var body: some View {
        
        VStack(spacing: 20) {
            
            Button(action: {
                present = true
            }, label: {
                
                Text("spawn translucent modal")
            })
            .fullScreenCover(isPresented: $present) {
                VStack(spacing: 20) {
                    Spacer()
                        .frame(maxWidth: .infinity, minHeight: 100)
                        .background(Color.black)
                        .opacity(0.3)
                    
                    Text("modal")
                }
                .background(Color.clear)
                
            }
            
            Text("some content")
            Text("some more content")
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

小智 15

可接受的解决方案有效,但并不理想,因为它需要遍历和猜测视图层次结构。

更可靠的选择是使用UIViewControllerRepresentable代替UIViewRepresentable,以便可以直接访问父控制器。

        .fullScreenCover(isPresented: $present) {
            VStack {
                Text("modal")
            }
            .background(Background()) // << helper !!
        }
Run Code Online (Sandbox Code Playgroud)
struct Background: UIViewControllerRepresentable {
    
    public func makeUIViewController(context: UIViewControllerRepresentableContext<Background>) -> UIViewController {
        return Controller()
    }
    
    public func updateUIViewController(_ uiViewController: UIViewController, context: UIViewControllerRepresentableContext<Background>) {
    }
    
    class Controller: UIViewController {
        override func viewDidLoad() {
            super.viewDidLoad()
            view.backgroundColor = .clear
        }
        
        override func willMove(toParent parent: UIViewController?) {
            super.willMove(toParent: parent)
            parent?.view?.backgroundColor = .clear
            parent?.modalPresentationStyle = .overCurrentContext
        }
    }
}

Run Code Online (Sandbox Code Playgroud)


Asp*_*eri 5

这是可能的解决方案

        .fullScreenCover(isPresented: $present) {
            VStack(spacing: 20) {
                Spacer()
                    .frame(maxWidth: .infinity, minHeight: 100)
                    .background(Color.black)
                    .opacity(0.3)
                
                Text("modal")
            }
            .background(BackgroundCleanerView())     // << helper !!
        }
Run Code Online (Sandbox Code Playgroud)

现在是帮手

struct BackgroundCleanerView: UIViewRepresentable {
    func makeUIView(context: Context) -> UIView {
        let view = UIView()
        DispatchQueue.main.async {
            view.superview?.superview?.backgroundColor = .clear
        }
        return view
    }

    func updateUIView(_ uiView: UIView, context: Context) {}
}
Run Code Online (Sandbox Code Playgroud)