How to have a fully functioning NavigationView in a .fullSizeContent window with SwiftUI

277 views Asked by At

I'm trying to get my NavigationView to fill the whole window. The List should stretch from the top to bottom edge of its window. But while the List looks correct at first with .fullSizeContentView added to NSWindow's styleMask the whole NavigationView shrinks down as soon as I select a list item.

To Prevent shrinking I found two options.

  1. Use a ZStack with Color-background, so the background will resize DetailView.
  2. Use a frame-modifier with maxWidth and maxHeight being .infinity

Both options will destroy the List's arrow key navigation though.

Which is the correct way to set up full size content with a NavigationView?

Below is the complete working sample code needed to replicate the problem. If you you want to test it, just replace the contents of those files in a fresh Swift macOS App on Catalina.

AppDelegate.swift

import Cocoa
import SwiftUI

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
    var window: NSWindow!

    func applicationDidFinishLaunching(_ aNotification: Notification) {
        let contentView = ContentView()

        window = NSWindow(
            contentRect: NSRect(x: 0, y: 0, width: 480, height: 300),
            styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView],
            // <---- remove .fullSizeContentView mask and layout will work without option 1 or 2 in ContentView
            backing: .buffered, defer: false)
        window.titlebarAppearsTransparent = true
        window.titleVisibility = .hidden
        window.isReleasedWhenClosed = false
        window.center()
        window.setFrameAutosaveName("Main Window")
        window.contentView = NSHostingView(rootView: contentView)
        window.makeKeyAndOrderFront(nil)
    }
}

ContentView.swift

import SwiftUI

let warners = ["Yacko","Wacko","Dot"]

struct WarnerView: View {
    var name: String
    var body: some View {
//        ZStack { // <---- Option 1: use ZStack with Color.clear
//            Color.clear
            VStack {
                Text(name)
                Text("Nothing to see here!")
            }
//            .frame(minWidth: 100, idealWidth: 100, maxWidth: .infinity, minHeight: 100, idealHeight: 100, maxHeight: .infinity, alignment: .center)
//          <---- Option 2: use only VStack with frame
//        } // <- closing bracket for ZStack
    }
}

struct ContentView: View {
    var body: some View {
        ZStack {
            Color.clear
            NavigationView {
                VStack(alignment: .leading) {
                    HStack {
                        Text("Warners")
                            .font(.headline)
                    }
                        .padding(16)
                    List(warners, id: \.self)
                     { warner in
                        NavigationLink(destination: WarnerView(name: warner)
                        ) {
                            Text(warner)
                        }
                    }.listStyle(SidebarListStyle())
                }
            }
        }
        .edgesIgnoringSafeArea(.all)
        .frame(minWidth: 600, minHeight: 400)
    }
}
1

There are 1 answers

3
Asperi On

As far as I understood here is way (tested with Xcode 12 / macOS 10.15.6). No changes to your above WarnerView.

demo

struct ContentView: View {
    var body: some View {
            NavigationView {
                List {
                  HStack {
                        Text("Warners")
                             .font(.headline)
                  }
                  ForEach(warners, id: \.self)
                    { warner in
                        NavigationLink(destination:
                            WarnerView(name: warner)
                                .frame(maxWidth: .infinity, maxHeight: .infinity)
                                ) {
                             Text(warner)
                        }
                  }
                }.listStyle(SidebarListStyle())

// uncomment below for default details area
//                  WarnerView(name: "")
//                      .frame(maxWidth: .infinity, maxHeight: .infinity)
        }
    }
}