NSWindow ContentView не охватывает полный размер окна - macOS & SwiftUI - PullRequest
3 голосов
/ 14 февраля 2020

Я запускаю новое приложение MacOS с SwiftUI, но у меня большая проблема. Приложению требуется полный размер contentView (под titleBar), но я не могу выполнить sh. В новом проекте использование раскадровок работает нормально, но с SwiftUI нет.

Мой код: enter image description here

Результат: enter image description here

И это должно выглядеть так: enter image description here

Есть идеи? Спасибо!

Ответы [ 2 ]

3 голосов
/ 16 февраля 2020

Я только что использовал следующий вариант в AppDelegate, содержимое ContentView и других может быть любым

func applicationDidFinishLaunching(_ aNotification: Notification) {
    // Create the SwiftUI view that provides the window contents.
    let contentView = ContentView()
        .edgesIgnoringSafeArea(.top) // to extend entire content under titlebar 

    // Create the window and set the content view. 
    window = NSWindow(
        contentRect: NSRect(x: 0, y: 0, width: 480, height: 300),
        styleMask: [.titled, .closable, .miniaturizable, .texturedBackground, .resizable, .fullSizeContentView],
        backing: .buffered, defer: false)
    window.center()
    window.setFrameAutosaveName("Main Window")

    window.titlebarAppearsTransparent = true // as stated
    window.titleVisibility = .hidden         // no title - all in content

    window.contentView = NSHostingView(rootView: contentView)
    window.makeKeyAndOrderFront(nil)
}
1 голос
/ 16 февраля 2020

Безопасная область не распространяется под прозрачной строкой заголовка. Вы можете использовать edgesIgnoringSafeArea, чтобы указать границам просмотра контента игнорировать безопасную область. Нечто похожее на ваш пример:

struct ContentView: View {
  var body: some View {
    HStack(spacing: 0) {
      Text("Hello, World!")
        .frame(maxWidth: 200, maxHeight: .infinity)
        .background(Color.red)
      Text("Hello, World!")
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .background(Color.black)
    }.edgesIgnoringSafeArea(.all)
  }
}

Обновление: Если вы хотите использовать NavigationView, вы также должны добавить edgesIgnoringSafeArea к его содержимому:

struct ContentView: View {
  var body: some View {
    NavigationView {
      Text("Hello, World!")
        .frame(maxWidth: 200, maxHeight: .infinity)
        .background(Color.red)
        .edgesIgnoringSafeArea(.all)

      Text("Hello, World!")
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .background(Color.black)
        .edgesIgnoringSafeArea(.all)

    }.edgesIgnoringSafeArea(.all)
  }
}

К сожалению, в данный момент изначально будет отображаться строка заголовка, по-видимому, до тех пор, пока вы не вызовете перерисовку полного окна. После того, как вы переместите окно на другой экран или скроете и покажете его снова, строка заголовка исчезнет. Итак, я предполагаю, что это будет исправлено в какой-то момент.

Прямо сейчас вы можете программно принудительно скрыть и показать, добавив

DispatchQueue.main.async {
  self.window.orderOut(nil)
  self.window.makeKeyAndOrderFront(nil)
}

после window.makeKeyAndOrderFront(nil) в applicationDidFinishLaunching , Однако это добавит очень короткую анимацию. Если вас это беспокоит, вы можете отключить это с помощью NSWindow.animationBehavior или чего-то подобного.

Обновление 2 : По-видимому, если вы удалите начальный window.makeKeyAndOrderFront(nil) и замените его с логами очереди отправки c выше он не будет анимирован. В итоге у вас будет

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, .texturedBackground],
      backing: .buffered, defer: false)
  window.titlebarAppearsTransparent = true
  window.center()
  window.setFrameAutosaveName("Main Window")
  window.contentView = NSHostingView(rootView: contentView)
  // window.makeKeyAndOrderFront(self) <- don't call it here
  DispatchQueue.main.async {
    self.window.orderOut(nil)
    self.window.makeKeyAndOrderFront(nil)
  }
}
...