Je démarre une nouvelle application macOS avec SwiftUI mais j'ai un gros problème. L'application a besoin d'un contentView
taille contentView
(sous titleBar
) mais je ne peux pas le faire. Sur un nouveau projet, l'utilisation de Storyboards fonctionne bien, mais pas avec SwiftUI.
Et cela devrait ressembler à ceci:
Des idées? Merci!
3 Réponses :
La zone de sécurité ne s'étend pas sous une barre de titre transparente. Vous pouvez utiliser edgesIgnoringSafeArea
pour indiquer à vos bords d'affichage de contenu d'ignorer la zone de sécurité. Quelque chose qui ressemble à votre exemple:
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) } }
Mise à jour: Si vous souhaitez utiliser un NavigationView, vous devez également ajouter edgesIgnoringSafeArea
à son contenu:
DispatchQueue.main.async { self.window.orderOut(nil) self.window.makeKeyAndOrderFront(nil) }
Malheureusement, cela affichera initialement une barre de titre pour le moment, apparemment jusqu'à ce que vous forciez une refonte complète de la fenêtre. Une fois que vous déplacez la fenêtre vers un autre affichage ou que vous la masquez et l'affichez à nouveau, la barre de titre disparaît. Donc, je suppose que cela sera corrigé à un moment donné.
À l'heure actuelle, vous pouvez forcer un masque et afficher par programmation en ajoutant
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) } }
après window.makeKeyAndOrderFront(nil)
dans applicationDidFinishLaunching
. Cela ajoutera cependant une très courte animation. Si cela vous dérange, vous pourrez peut-être désactiver cela avec NSWindow.animationBehavior
ou quelque chose comme ça.
Mise à jour 2 : Apparemment, si vous supprimez le window.makeKeyAndOrderFront(nil)
initial window.makeKeyAndOrderFront(nil)
et le remplacez par la logique de file d'attente de distribution au-dessus, il ne s'animera pas. Donc à la fin vous aurez
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) } }
La bonne façon est d'utiliser NagivationView. Dans macOS, vous ne devez pas utiliser HStack pour la navigation. Cela fonctionne bien avec votre solution, mais pas avec NavigationView. Je laisse cette réponse en attente en attendant d'autres options. Merci!
Vous n'avez rien dit sur la navigation :) J'ai mis à jour ma réponse.
En quoi est-ce moins précis?
C'est difficile à évaluer. Les deux réponses sont correctes, mais l'autre a moins de code, plus générale, s'applique à tout le contenu de la vue, etc. J'ai beaucoup réfléchi à la meilleure réponse. Si je pouvais, je vous donnerais les points à tous les deux. Je suis désolé... :(
Je peux imaginer, mais je comprends que vous voulez vous bâtir une réputation.
Je viens d'utiliser la variante suivante dans AppDelegate
, le contenu de ContentView
et d'autres peuvent être
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) }
Merci, c'est la réponse la plus précise et la plus simple
Il est intéressant de noter que la spécification des bords en dehors de ContentView
a un effet différent. C'est soit un bug, soit SwiftUI a plus de problèmes de composition que je ne le pensais. Il est temps pour plus d'expériences :) Merci pour votre réponse!
Pour mémoire: si j'ai un NavigationView
à l'intérieur du ContentView
j'ai toujours besoin d'un edgesIgnoringSafeArea
sur le NavigationView
.
Juste pour plus d'informations sur le cycle de vie de l'application SwiftUI.
Vous devez définir le style de fenêtre sur HiddenTitleBarWindowStyle:
WindowGroup { ContentView() }.windowStyle(HiddenTitleBarWindowStyle())
Et quel est le problème avec ça? Voulez-vous une fenêtre sans barre de titre?
Oui, j'ai besoin d'une fenêtre sans barre de titre mais avec des boutons de fermeture, de réduction et de redimensionnement. Deux vues (rouge et noir) doivent s'étendre sous la barre de titre et les boutons