102 votes

Accéder à une nouvelle vue avec SwiftUI

J'ai une vue de base avec un bouton utilisant SwiftUI et j'essaie de présenter un nouvel écran/vue lorsque le bouton est touché. Comment dois-je m'y prendre ? Suis-je censé créer un délégué pour cette vue qui dira au programme de l'application SceneDelegate pour présenter un nouveau contrôleur de vue ?

import SwiftUI

struct ContentView : View {
    var body: some View {
        VStack {
            Text("Hello World")
            Button(action: {
                //go to another view
            }) {
                Text("Do Something")
                    .font(.largeTitle)
                    .fontWeight(.ultraLight)
            }
        }
    }
}

89voto

Jake Points 215

La clé est d'utiliser une NavigationView et une NavigationLink :

import SwiftUI

struct ContentView : View {
    var body: some View {
        NavigationView {
            VStack {
                Text("Hello World")
                NavigationLink(destination: DetailView()) {
                    Text("Do Something")
                }
            }
        }
    }
}

1 votes

NB Pour l'instant, cette approche ne fonctionne pas sur l'Apple Watch car "NavigationView" n'est pas disponible dans watchOS. Vous pouvez utiliser uniquement NavigationLink comme expliqué aquí

1 votes

Cela fonctionne, mais cela couple étroitement ces vues. Existe-t-il une meilleure approche où une vue ne connaît pas l'autre ?

41 votes

Y a-t-il un moyen de faire cela avec un Button au lieu d'un affreux NavigationLink ?

83voto

George_E_2 Points 622

Il ne s'agissait pas de la réponse principale, mais plutôt d'une méthode alternative si vous ne voulez pas de la barre de navigation. Voir La réponse de Jake ci-dessous pour la manière normale de procéder avec NavigationView & NavigationLink . J'espère que ces informations vous seront toujours utiles ou qu'elles vous mettront sur la bonne voie.

Si vous essayez juste d'obtenir un NavigationLink travailler avec un Binding vous pouvez utiliser le même NavigationLink comme je l'ai fait avec le isActive paramètre de liaison.

Bref, revenons à la réponse


J'ai créé un modificateur de vue pour cela. Cela signifie également qu'il n'y a pas de barre de navigation. Vous pouvez l'appeler comme ça :

.navigate(to: MainPageView(), when: $willMoveToNextScreen)

Il peut être attaché à n'importe quoi, donc je l'attache généralement à l'extrémité du corps, par exemple :

@State private var willMoveToNextScreen = false

var body: some View {
    VStack {
        /* ... */
    }
    .navigate(to: MainPageView(), when: $willMoveToNextScreen)
}

Code (n'oubliez pas de import SwiftUI ) :

extension View {
    /// Navigate to a new view.
    /// - Parameters:
    ///   - view: View to navigate to.
    ///   - binding: Only navigates when this condition is `true`.
    func navigate<NewView: View>(to view: NewView, when binding: Binding<Bool>) -> some View {
        NavigationView {
            ZStack {
                self
                    .navigationBarTitle("")
                    .navigationBarHidden(true)

                NavigationLink(
                    destination: view
                        .navigationBarTitle("")
                        .navigationBarHidden(true),
                    isActive: binding
                ) {
                    EmptyView()
                }
            }
        }
        .navigationViewStyle(.stack)
    }
}

1 votes

Une approche soignée, bien qu'elle semble briser mes vues préexistantes avec un style déjà appliqué.

0 votes

Très concis, soigné. meilleur

2 votes

Beau travail. Une dernière chose, est-il possible de modifier l'animation de la navigation ? Elle était toujours de gauche à droite par défaut.

13voto

Mohsen mokhtari Points 1242

Si no veulent montrer le navigationView vous pouvez le cacher dans la destination.

struct ContentViewA : View {
    var body: some View {
        NavigationView {
            VStack {
                Text("Hello World")
                NavigationLink(destination: ContentViewB()) {
                    Text("Go To Next Step")
                }
            }
        }
    }
}

struct ContentViewB : View {
        var body: some View {
            NavigationView {
                VStack {
                    Text("Hello World B")

                }.navigationBarTitle("")
                .navigationBarHidden(true)
            }
        }
    }

ou si vous voulez le cacher en fonction de conditions, vous pouvez utiliser @State pour changer la visibilité.

0 votes

Nota: .navigationBarTitle("") masque le texte, mais laisse maladroitement l'espacement dans une vue vide. On pourrait donc s'en sortir en utilisant simplement le modificateur .navigationBarHidden(true) et ensuite mettre en place un bouton de retour personnalisé ou une navigation alternative.

2 votes

Le problème avec l'utilisation d'une vue de navigation et le simple fait de cacher des choses est que 1) vous êtes toujours dans un modèle push / pop et si vous n'avez jamais l'intention de revenir en arrière (pop), alors cette vue reste là à manger de la mémoire et des cycles (selon sa structure et sa complexité), et n'est jamais éliminée. Peut-être que ce n'est pas un problème dans le grand schéma, mais cela me semble un peu huileux.

7voto

bulutgonulalan Points 167

Je pense que c'est le moyen le plus simple et le plus clair. Utilisez fullScreenCover après l'outil UI.

Button(action: {
         //code
         }){
           Text("Send")
         }.fullScreenCover(isPresented: self.$model.goToOtherView, content: {
                    OtherView()
                })

0 votes

Le problème, c'est qu'il n'y a pas de couleur de fond pour le FullScreenCover.

0 votes

Intéressant, mais je vois aussi que c'est une fonctionnalité réservée à iOS 14.0 dans XCode.

3voto

Sada Points 1298

Voici une autre façon de présenter une vue SANS utiliser NavigationView. Cela ressemble à la méthode de UIKit UIModalPresentationStyle.currentContext .

struct PresenterButtonView: View {
var body: some View {
    PresentationButton(Text("Tap to present"),
                       destination: Text("Hello world"))
}}

15 votes

Hmmm. Où est PresentationButton de ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X