I am trying to make a "FullScreenModalView" where you can send any view with a fixed height and width and it will show with a modal presentation. It is working perfectly but I can't make the "Presentation Hosting Controller" background color transparent. I tried a couple of solutions like setting a custom transparent view as a background view, but still it has no effect on the "Presentation Hosting Controller" background color.
But in the view hierarchy I can see the background color of the Presentation Hosting Controller is white, which I need to set as a clear color.
My code:
ContentView
import SwiftUI
struct ContentView: View {
@State private var isShowingCommonMenu = false
@State private var isPresented = false
var body: some View {
VStack {
Button {
//MARK: Show Network Configure List
self.isShowingCommonMenu.toggle()
} label: {
Text("GO")
}
.fullScreenCover(isPresented: $isShowingCommonMenu) {
NavigationStack {
GeometryReader { geometry in
FullScreenModalView(isShowingCommonMenu: $isShowingCommonMenu, childViewWidth: (geometry.size.width - geometry.size.width/10), childViewHeight: geometry.size.height) {
TheViewToBeLoadedView()
}
}
}
}
}
.frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
.background(Color.orange)
.padding()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
FullScreenModalView
import SwiftUI
struct FullScreenModalView<Content: View>: View {
@Binding var isShowingCommonMenu: Bool
var childViewWidth: CGFloat
var childViewHeight: CGFloat
let content: () -> Content
var body: some View {
ZStack {
Color.black.opacity(0.4)
.edgesIgnoringSafeArea(.all)
.onTapGesture {
//Dismiss the modal view when the user taps outside of it
dismiss()
}
VStack {
content()
.background(ClearBackgroundView())
}
.frame(width: childViewWidth, height: childViewHeight)
.background(Color.white)
.cornerRadius(10)
.overlay(
Button {
dismiss()
} label: {
DismissButton()
}, alignment: .topTrailing)
}
.ignoresSafeArea(.keyboard)
.background(TransparentBackground())
}
private func dismiss() {
isShowingCommonMenu = false
}
}
struct FullScreenModalView_Previews: PreviewProvider {
static var previews: some View {
FullScreenModalView(isShowingCommonMenu: .constant(true), childViewWidth: 200, childViewHeight: 200) {
Text("This is a custom preview view")
}
}
}
struct TransparentBackground: 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) {}
}
struct DismissButton: View {
var body: some View {
ZStack {
Circle()
.frame(width: 30, height: 30)
.foregroundColor(.white)
.opacity(0.6)
Image(systemName: "xmark")
.imageScale(.medium)
.frame(width: 44, height: 44)
.foregroundColor(Color(.label))
}
}
}
And the sample view that I want to load:
import SwiftUI
struct TheViewToBeLoadedView: View {
var body: some View {
GeometryReader { geometry in
Text("TheViewToBeLoadedView")
.frame(width: geometry.size.width, height: geometry.size.height, alignment: .center)
.background(Color.yellow)
}
}
}
struct TheViewToBeLoadedView_Previews: PreviewProvider {
static var previews: some View {
TheViewToBeLoadedView()
}
}
Apply .background(TransparentBackground()) on the Content in .fullScreenCover
e.g.
struct ContentView: View {
@State private var showingFullscreenModal: Bool = false
var body: some View {
VStack {
Button {
showingFullscreenModal.toggle()
} label: {
Text("Show Fullscreen Modal")
}
}
.frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
.background(.orange)
.fullScreenCover(isPresented: $showingFullscreenModal) {
SubView(showing: $showingFullscreenModal, width: 300, height: 400)
.background(TransparentBackground()) // <--- Here
}
}
}
struct TransparentBackground: 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) {}
}
struct SubView: View {
@Binding var showing: Bool
let width: CGFloat
let height: CGFloat
var body: some View {
VStack {
Text("Hello World")
Button {
showing = false
} label: {
Text("Close")
}
}
.frame(width: width, height: height)
.background(.teal)
}
}
So, in your case, apply .background(TransparentBackground()) on NavigationStack in .fullScreenCover