How do I create a NSViewRepresentable view with children?

I am trying to make a form that is transparent. The only way I found to do this, is to use a NSVisualEffectsView (see code below).


My problem is that I want the view to behave like a normal SwiftUI container (for example a Form), and that it takes the size of its children. I want the resulting window to take the size defined by the children, in this case the "Hallo World" Text view.


How do I do this?


import SwiftUI

struct EffectsView: NSViewRepresentable {
  func makeNSView(context: Context) -> NSVisualEffectView {
    return NSVisualEffectView()
  }
  
  func updateNSView(_ nsView: NSVisualEffectView, context: Context) {
    // Nothing to do.
  }
}

struct ContentView: View {
  var body: some View {
    ZStack {
      EffectsView()
      Text("Hallo World")
    }
  }
}


struct ContentView_Previews: PreviewProvider {
  static var previews: some View {
    ContentView()
  }
}

Accepted Reply

In macOS your window size is explicitly set in applicationDidFinishLaunching(_:). Look at the documentation for the .fullSizeContentView window style mask to see some other options, though. The window is unlikely to actually resize to fit its content, though—you'd need to post that information somewhere courtesy of a GeometryReader I suspect.


As far as having the effects view match the size of the content, you can use .background() to get that behavior:


var body: some View {
  Text("Hallo World")
    .background(EffectsView())
}


Also note that the List type doesn't seem to respect the .background() modifier. Happily, though, Form on macOS is just a regular view with a clear background, so this still works there, at least.

Replies

In macOS your window size is explicitly set in applicationDidFinishLaunching(_:). Look at the documentation for the .fullSizeContentView window style mask to see some other options, though. The window is unlikely to actually resize to fit its content, though—you'd need to post that information somewhere courtesy of a GeometryReader I suspect.


As far as having the effects view match the size of the content, you can use .background() to get that behavior:


var body: some View {
  Text("Hallo World")
    .background(EffectsView())
}


Also note that the List type doesn't seem to respect the .background() modifier. Happily, though, Form on macOS is just a regular view with a clear background, so this still works there, at least.