6
votes

Comment mettre le bouton SwiftUI dans NSToolbar?

Voici comment SwiftUI peut être inséré dans NSToolbar aide d'un contrôleur de vue accessoire:

HStack {
  Text("Hey")
    .offset(x: 0, y: -1)
  Button(action: {}) {
    Text("SwiftUI")
      .offset(x: 0, y: -7)
  }
}
.font(.caption)

Le code ci-dessus fonctionne:

Si nous insérons un bouton cependant:

HStack {
  Text("Hey")
  Button(action: {}) {
    Text("SwiftUI")
  }
}

Cela ne fonctionnerait pas comme prévu:

Aucune suggestion?

PS Ceci est une solution de travail:

import SwiftUI
import PlaygroundSupport

var hostingView = NSHostingView(rootView:
  ZStack {
    Color.clear
    HStack {
      Text("Hey")
      Text("SwiftUI")
    }
  }
  .padding()
  .edgesIgnoringSafeArea(.all)
)
hostingView.frame.size = hostingView.fittingSize

let titlebarAccessory = NSTitlebarAccessoryViewController()
titlebarAccessory.view = hostingView
titlebarAccessory.layoutAttribute = .trailing

let mask: NSWindow.StyleMask = [.titled, .closable, .miniaturizable, .resizable]
let window = NSWindow(
  contentRect: .init(x: 0, y: 0, width: 480, height: 300),
  styleMask: mask, backing: .buffered, defer: false)
window.center()
window.contentView = NSHostingView(rootView: Color(.windowBackgroundColor))
window.toolbar = .init()
window.titleVisibility = .hidden
window.addTitlebarAccessoryViewController(titlebarAccessory)

PlaygroundPage.current.liveView = window.contentView?.superview


5 commentaires

Ce n'est certainement pas une bonne réponse, mais vous pouvez utiliser .padding(EdgeInsets(top: -7, leading: 0, bottom: 0, trailing: 0)) sur le texte du bouton. Certainement buggy cependant.


@LucasDerraugh C'est une excellente réponse en fait. Pouvez-vous le soumettre?


@Vadim Je suis curieux de savoir pourquoi vous utilisez un ZStack .


@BijoyThangaraj Ça fait moins bizarre que H ou V dans ce cas particulier 🙂


J'ai remarqué qu'apparemment, ce bogue ne se produit PAS lorsque l'utilisateur final rend la fenêtre en plein écran, rendant toutes les solutions de contournement (aussi laides qu'elles soient) inutilisables ... :(


4 Réponses :


1
votes

Publier mon commentaire comme réponse par demande. Pas nécessairement une solution fiable, mais comme solution de contournement, vous pouvez utiliser

Text("SwiftUI")
  .padding(EdgeInsets(top: -7, leading: 0, bottom: 0, trailing: 0))

ou .offset sur le texte dans le bouton. Aucune garantie sur la durée de cette solution.


2 commentaires

Cela peut toujours ne pas fonctionner lorsque / si l'utilisateur rend la fenêtre en plein écran, malheureusement. De plus, la valeur -7 est "variable" et dépend de la hauteur de la vue réelle.


Comme je l'ai dit, il s'agit plus d'une solution de contournement que d'une solution. On m'a demandé de poster mon commentaire en guise de réponse.



0
votes

L'élément de la barre d'outils a plus d'espace vertical. Pour corriger cette utilisation de la vue Spacer, il poussera le bouton vers le haut:

VStack {
  Button(action: {}) {
    Text("Text")
  }.frame(height: 22)

  Spacer()
}


1 commentaires

Cela fonctionne, sauf s'il existe un bouton de barre d'outils sous la vue des accessoires, il n'est pas accessible par les API d'accessibilité (comme vous pouvez le voir en exécutant l'inspecteur d'accessibilité), ce qui empêche les appareils d'assistance de pouvoir accéder à ces boutons.



2
votes

La façon dont je l'ai finalement géré (le faire fonctionner également lorsque l'utilisateur rend la fenêtre plein écran ET quelle que soit la hauteur * du contenu) est ci-dessous. Notez que j'utilise la vue Toolbar dans un NSHostingView dans NSTitlebarAccessoryViewController d'une application macOS construite avec la version la plus récente de Xcode (évidemment, sur macOS Catalina).

Choses importantes: * vous devez toujours configurer une hauteur fixe pour le cadre (mais au moins vous ne comptez pas sur la "variable" -7) et un décalage vers le haut de la moitié de la hauteur réelle UNIQUEMENT lorsqu'il y a un encart supérieur de zone de sécurité (en mode plein écran, apparemment, ce n'est pas le cas) et donc GeometryReader est un must:

let toolbar = NSHostingView(rootView: Toolbar())
toolbar.frame.size = toolbar.fittingSize
let toolbarController = NSTitlebarAccessoryViewController()
toolbarController.view = toolbar
window.addTitlebarAccessoryViewController(toolbarController)

et où la fenêtre est créée:

struct Toolbar : View {
    var body: some View {
        GeometryReader { geometry in
            VStack {
                Text("1st row")
                Text("2nd row")
            }
            .offset(y: geometry.safeAreaInsets.top > 0 ? -geometry.size.height / 2 : 0)
        }
        .frame(height: 42)
    }
}


0 commentaires

0
votes

Il semble que l'application de PlainButtonStyle au bouton aide. Le style par défaut fait une magie étrange qui brise la mise en page dans NSToolbar.


0 commentaires