19

Anyone knows how to to make the modal view with a transparent background.

Exactly like the below link in swift

Swift Modal View Controller with transparent background

  • I stand corrected from my previous comment, so I deleted it (and will upvote your question). Right now it appears you *can* give a background to the modal view by using a `Rectangle` inside a `ZStack`. BUT... the default for a modal view seems to be based on the light/dark mode setting. If you make that Rectangle fill be `Color.clear, you'll still have a background that covers the underlying view.... –  Aug 23 '19 at 13:24
  • Hopefully a future version of SwiftUI will have your feature, but I'm think your best bet is to not use a modal but instead create a full screen view with a transparent background and anti it onto the screen and provide a way to dismiss it. Since a transparent modal won't show it's edges, you'll essentially *fake* a modal. –  Aug 23 '19 at 13:25
  • mmh could be a solution something like that (is just a View that appears inside a ZStack) https://github.com/peppesapienza/random-code/blob/master/transparent-modal-swiftUI.swift ? – Giuseppe Sapienza Aug 24 '19 at 09:47

6 Answers6

12

I am using coordinator pattern, creating view in assembly

let view = UIHostingController(rootView: swiftuiview)
view.view.backgroundColor = .clear

inside router just present this UIHostingController

module.modalPresentationStyle = .overCurrentContext
navigationController.present(module, animated: animated, completion: nil)
saniaxxx26
  • 442
  • 1
  • 3
  • 10
  • Unfortunately it appears that the UIHostingController's backgroundColor does not contain a .clear – Legolas Wang Feb 17 '20 at 10:55
  • Found a way to make the view atleast clear by setting view.view.background to nil instead of .clear, then all you do is set the opacity to zero ether on the hosting controller level or on the SwftUI View itself – Ash-Bash32 Apr 07 '20 at 14:16
5

If you wanting to blur the background of a SwiftUI from UIKit Project and are possibly using SwiftUI View for a Modal View then I had the same problem recently and created a UIViewController that takes the UIHostController (UIViewController basically), then alters the HostingController View's alpha, puts a blur at the back and presents it to the parent view.

I Have created a gist with the file in it for public use https://gist.github.com/Ash-Bash/93fd55d89c1e36f592d3868f6b29b259

Heres the working example:

// Initialises BlurredHostingController
var blurredHostingController = BlurredHostingController()

// Sets the Hosting View for the SwiftUI View Logic
blurredHostingController.hostingController = UIHostingController(rootView: ContentView())

// Blur Tweaks for blurredHostingController
blurredHostingController.blurEffect = .systemMaterial
blurredHostingController.translucentEffect = .ultrathin

// Presents View Controller as a Modal View Controller
self.present(blurredHostingController animated: true, completion: nil)

Here's the result from macCatalyst enter image description here

Ash-Bash32
  • 423
  • 6
  • 17
4

Present:

let rootView = Text("Hello world")
let controller = UIHostingController(rootView: rootView)
controller.view.backgroundColor = .clear
UIApplication.shared.windows.first?.rootViewController?.present(controller, animated: true)

Dismiss:

UIApplication.shared.windows.first?.rootViewController?.dismiss(animated: true)
Lorenzo Fiamingo
  • 3,251
  • 2
  • 17
  • 35
2

I didn't get the ideal way to do so, but I got a workaround for this.

So, In order to present a view modally, you can take a ZStack and group multiple views in it and handle it with a @State variable like this.

Here I have given the background colour to the view for better explanation.

struct ContentView : View {
   @State private var showModally = false
   var body : some View {
    ZStack {
        Color.red
        VStack {
            Button(action: {
                withAnimation{
                    self.showModally = true
                }
            }) {
                Text("Push Modally")
            }
        }
        
        ModalView(show: $showModally)
            .offset(y: self.showModally ? 0 : UIScreen.main.bounds.height)
            .animation(.spring())
        
    }
  }
}

struct ModalView: View {
  @Binding var show : Bool
  var body: some View {
    VStack {
        Spacer()
        
        VStack {
            Color.white
        }
        .frame(height : 400)
        .cornerRadius(10)
        .padding(.horizontal)
    }
    .background(Color.clear)
    .onTapGesture {
        self.show = false
    }
  }
}

In this, the Modal View will be presented modally over the content view and will be dismissed by a tap.

Anshuman Singh
  • 1,018
  • 15
  • 17
2

iOS 16.4+

You can use the new modifier to display a fullscreen modal with a transparent background:

presentationBackground(_:)

Sets the presentation background of the enclosing sheet using a shape style.

Here's an example:

struct ContentView: View {
    @State private var showSettings = false

    var body: some View {
        Button("View Settings") {
            showSettings = true
        }
        .fullScreenCover(isPresented: $showSettings) {
            SettingsView()
                .presentationBackground(.thickMaterial) // <-- this 
        }
    }
}
Ajith Renjala
  • 4,934
  • 5
  • 34
  • 42
0

Add this on parent view, assign modalPresentationStyle as a .formSheet and set size as parent view by assigning preferredContentSize to hostingVC.

  if segue.identifier == "AnotherView", let hostingController = segue.destination as? HostingSwiftUIView {
    hostingController.modalPresentationStyle = .formSheet
    hostingController.preferredContentSize = CGSize(width: 700, height: 300) // customise as per View
    hostingController.rootView = AnyView(AnotherView())
}

Here is Child view as present view modally.

struct AnotherView : View {
    var body: some View {
        Text("Second View")
            .bold()
            .font(.largeTitle)
    }
}

It will look like: enter image description here

Nav Brar
  • 202
  • 1
  • 9