[Résolu] Afficher une fenêtre menu à partir d'une toolBar en SwiftUI

Bonjour, je souhaite pouvoir afficher des fenêtres à partir de boutons dans la toolbar comme on le faisait en Swift uikit. (fenêtre au milieu de l’écran pour des explications par exemple, des options …)
j’ai bien créé ma toolbar et mon bouton, mais mon problème c’est que ma fenêtre s’affiche dans ma toolbar. Car elle dépend du bouton de cette même toolbar.

import SwiftUI

struct FenetreMenu: View {
var largeurFenetre:CGFloat
var hauteurFenetre:CGFloat

var body: some View {
    ZStack(alignment: .center) {
        Rectangle()
            .fill(Color.purple)
            .frame(width: largeurFenetre, height: hauteurFenetre, alignment: .center)
            .cornerRadius(10)
            .shadow(color: .black, radius: 2, x: 2, y: 2)
    }
}

}

import SwiftUI
struct BoutonFermeture: View {
@Binding var fermetureFenetre:Bool
var couleurFond:Color
var couleurTexte : Color
var body: some View {
Button(action: {
self.fermetureFenetre.toggle()
}, label: {
Text(« Fermer »)
.padding()
.background(couleurFond)
.foregroundColor(couleurTexte)
.cornerRadius(10)
.shadow(color: .black, radius: 2, x: 2, y: 2)
})
}
}

import SwiftUI

struct AproposContenu: View {
var monTexte:String
var couleurTexte:Color
var body: some View {
Text(monTexte)
.foregroundColor(couleurTexte)
}
}

import SwiftUI

struct ContentView: View {
@State var montrerFenetre:Bool = false
var body: some View {
NavigationView {

        Text("Application principale")
            .padding()
        
            .navigationTitle("Exemple Menu")
        
            .toolbar {
                ToolbarItem(placement:.bottomBar) {
                    ZStack {
                        Button(action: {
                            self.montrerFenetre.toggle()
                        }, label: {
                            Text("Menu")
                        })
                        if montrerFenetre {
                            ZStack(alignment: .center) {
                                FenetreMenu(largeurFenetre: 175, hauteurFenetre: 105)
                                VStack {
                                    AproposContenu(monTexte: "Mon menu", couleurTexte: .black)
                                    BoutonFermeture(fermetureFenetre: $montrerFenetre, couleurFond: .white, couleurTexte: .red)
                                }
                            }
                        }
                    }
                    
                }
            }
    }
}

}

exemple complet sur GitHub : MenuApplication

Si je supprime la toolbar et que je mets mon bouton au milieu de l’écran, tout fonctionne.
Je n’ai surement pas la bonne approche en SwiftUI. Si d’autres ici ont déjà fait des fenêtres pour leurs applications, je veux bien votre vision.

Attends, si je me souviens bien, en UIkit, on passait d’un ViewController à un autre, avec les boutons de la tabBar, on n’ouvrait pas exactement des fenêtres ou des popovers ; si c’est ce que tu veux faire, pourquoi pas un NavigationLink, et sinon, pourquoi pas, plutôt qu’un bouton, un .onTapGesture ? J’essaie de bien comprendre, mais je suis sans doute aussi en difficulté que toi sinon plus.

Bonjour,

Attends, si je me souviens bien, en UIkit, on passait d’un ViewController à un autre, avec les boutons de la tabBar, on n’ouvrait pas exactement des fenêtres ou des popovers ; si c’est ce que tu veux faire, pourquoi pas un NavigationLink, et sinon, pourquoi pas, plutôt qu’un bouton, un .onTapGesture ? J’essaie de bien comprendre, mais je suis sans doute aussi en difficulté que toi sinon plus.

Pas du tout,
voilà ce que je faisais avec swiftUIKIT
voir ka video en lien sur une de mes « applis » video exemple

Le code Swift UIKIT
import UIKit

class VuePersonnalisee: UIView {

override init(frame: CGRect) {
    super.init(frame: frame)
}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}

func miseEnPlace() {
    layer.cornerRadius = 10
    layer.shadowRadius = 5
    layer.shadowOpacity = 1
    layer.shadowOffset = CGSize(width: 5, height: 5)
    layer.shadowColor = UIColor.black.cgColor
}
    
    // style de la vue 
func apparenceVue(formeRonde:Bool, visible:Bool, ombre:Bool, bordure:Bool) {
    // pas ronde et pas d'ombre
    if formeRonde == false  && ombre == false {
        layer.cornerRadius = 20
        
        // ronde sans ombre
    } else if formeRonde == true  && ombre == false {
        layer.cornerRadius = layer.frame.width / 2
        
        // pas ronde avec une ombre
    }  else if formeRonde == false  && ombre == true {
        layer.cornerRadius = 20
        layer.shadowRadius = 15
        layer.shadowOpacity = 1
        layer.shadowOffset = CGSize(width: 5, height: 5)
        layer.shadowColor = UIColor.black.cgColor
        
       //ronde avec une ombre
    }  else if formeRonde == true  && ombre == true {
        layer.cornerRadius = layer.frame.width / 2
        layer.shadowRadius = layer.frame.width / 2
        layer.shadowRadius = 15
        layer.shadowOpacity = 1
        layer.shadowOffset = CGSize(width: 5, height: 5)
        layer.shadowColor = UIColor.black.cgColor
    }
    // visible ou pas 
    if visible == false {
        alpha = 0
    } else {
        alpha = 1
    }
    
    // bordure a    autour de la fenetre
    if bordure == true {
        layer.borderColor = UIColor.black.cgColor
        layer.borderWidth = 2
    }
}

// creer le degradé 
func degradeDeCouleur(_ couleurs: [CGColor],debutDaPoint:CGPoint, finDePoint:CGPoint, positionCouleursDegrade:NSNumber,degradeFormeRond:Bool, apercusCouleur:Bool)  {
    let degrade = CAGradientLayer()
    degrade.colors = couleurs
    degrade.startPoint = debutDaPoint //CGPoint(x: 0, y: 1)
    degrade.endPoint = finDePoint //CGPoint(x: 1, y: 0)
    degrade.locations = [0.0,positionCouleursDegrade] //position de 2eme couleur à la vue
    degrade.frame = self.bounds
    if degradeFormeRond == true {
        degrade.cornerRadius = layer.frame.width / 2
    }
    if apercusCouleur == true {
        layer.addSublayer(degrade)
    } else {
        layer.insertSublayer(degrade, at: 0)
    }
}

}

Et voilà ce que j’arrive à faire avec le code en SwiftUI de mon premier message, c’est presque bon sauf que la fenêtre ne s’affiche pas au milieu.

voir la video: ouvertureFenetre
le code : Exemple

Avec un .offset(y: …) à la racine de la vue de ta fenêtre flottante çà ne marche pas ?

Bonjour,

J’ai déjà essayé, je n’y suis pas arrivé, je pense que le problème est que le bouton qui déclenche la fonction se trouve dans le toolbar, c’est pour cela que la fenêtre s’affiche dans la toolbar.

Merci de votre aide.

Salut,
Ton menu est dans la toolbar donc c’est normal quelle s’ouvre dedans, il faut sortie ton menu et avec state tu l’ouvre ou le referme avec swiftUI il faut pensé en composant

Bonjour,

Merci je vais essayer de faire comme cela, effectivement.
si je te suis bien il faut que mon bouton et mon menu ne se trouve pas dans la toolbar mais en composant, Ce même composant doit être appeler dans la toolbar. (comment mon composant disparaît je vais regarder).

J’ai une question, j’aimerais savoir si des personnes ici ont déjà développé des applications complètes en SwiftUI. Parque je m’aperçois d’une chose à titre personnel, je ne suis pas prêt de le faire, car tout ce que savais faire en swiftUIKIT avec des animations, des menus qui s’ouvre, gérer les GPS, afficher des cartes… j’ai énormément de mal en SwiftUI et sur le net on trouve des exemples basiques, mais si on souhaite sortir de ses choses basiques… pour faire une véritable application les exemples sont rares.

Mon propos concerne surtout dans le positionnement des éléments. j’ai l’impression que même sans utiliser les contraintes visuelles, en programmant par le code on était plus libre.

Je me trompe surrement.

Bonsoir,

avec state tu l’ouvres ou le referme avec swiftUI il faut pensé en composant

Je viens de faire l’essai cela ne fonctionne pas, je ne sais pas. Si toi tu arrives à le faire fonctionner comme tu me l’ as décrit.

Merci d’avoir essayé.

Tu souhaites bien réaliser quelque chose comme ceci ?

Merci à toi @East d’avoir corriger mon erreur que jamais pas vu. Et merci à tous d’avoir regardé. :smiley:

1 « J'aime »