I need to push a modal view from a button inside a view component, but should only be covering the bottom half of the screen height, the top half a semi transparent background(black with opacity 30%). Setting the opacity for the topmost view inside the fullscreenCover view builder doesnt work. Any help would be appreciated.
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")
}
}
}
Here is possible solution
.fullScreenCover(isPresented: $present) {
VStack(spacing: 20) {
Spacer()
.frame(maxWidth: .infinity, minHeight: 100)
.background(Color.black)
.opacity(0.3)
Text("modal")
}
.background(BackgroundCleanerView()) // << helper !!
}
and now helper
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) {}
}
The accepted solution works but isn't ideal, as it requires traversing and guessing the view hierarchy.
A more reliable option would be to use UIViewControllerRepresentable
instead of UIViewRepresentable
, so that the parent controller can be accessed directly.
.fullScreenCover(isPresented: $present) {
VStack {
Text("modal")
}
.background(Background()) // << helper !!
}
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
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With