34
votes

Accéder à une nouvelle vue en utilisant SwiftUI

J'ai une vue de base avec un bouton en utilisant SwiftUI et j'essaie de présenter un nouvel écran / vue lorsque le bouton est appuyé. Comment puis-je faire cela? Suis-je supposé créer un délégué pour cette vue qui indiquera à SceneDelegate l'application de 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)
            }
        }
    }
}


0 commentaires

12 Réponses :


38
votes

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

import SwiftUI

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


3 commentaires

NB Pour le moment, cette approche ne fonctionne pas sur Apple Watch car 'NavigationView' n'est pas disponible dans watchOS. Vous ne pouvez utiliser que NavigationLink comme expliqué ici


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


Existe-t-il un moyen de faire cela avec un Button au lieu d'un moche NavigationLink?



0
votes

Vous devez créer un DetailView comme LandmarkDetail () et appeler un NavigationButton avec la destination comme LandmarkDetail (). La vue détaillée était maintenant ouverte.

Pour passer des valeurs aux moyens d'écran de détail. en envoyant comme ci-dessous le code.

struct LandmarkList: View {
    var body: some View {
        NavigationView {
            List(landmarkData) { landmark in
                NavigationButton(destination: LandmarkDetail()) {
                    LandmarkRow(landmark: landmark)
                }
            }
            .navigationBarTitle(Text("Landmarks"))
        }
    }
}


0 commentaires

9
votes

Voici une autre façon de présenter une vue SANS utiliser NavigationView. C'est comme UIModalPresentationStyle.currentContext d'UIKit.

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


0 commentaires

2
votes

L'OP a reçu une réponse plusieurs fois ici, mais je voulais juste montrer également les aspects intéressants de SwiftUI en montrant si vous avez la vue A avec des données que la vue B utilisera également, vous pouvez transmettre des données en créant un @State dans la vue A et déclarer la même variable avec la déclaration @Binding dans la vue B

struct ViewB : View {
    @Binding var myItems: [Items]
    var body: some View {
        NavigationView {
            List{
                ForEach(myItems.identified(by: \.self)) {
                    Text($0.itemName)
                }
            }.navigationBarTitle(Text("My Items"))
        }
    }
}
struct ViewA : View {
    @State var myItems: [Items]
    var body: some View {
        NavigationView {
            VStack {
                NavigationButton(destination: ViewB(items: $myItems)) {
                    Text("Go To ViewB")
                }
            }
        }
    }
}


0 commentaires

0
votes

Vous ne pouvez plus utiliser NavigationButton. Au lieu de cela, vous devez utiliser NavigationLink.

struct ContentView: View {
    var body: some View {
        NavigationView {
            NavigationLink(destination: DetailView()) {
                Text("Push new screen")
            }
        }
    }
}


0 commentaires

1
votes

Nous pouvons maintenant utiliser NavigationLink


Déposer un:

struct secondView: View {
var body: some View {
    VStack {
    VStack(alignment: .leading) {
        Text("Turtle Rock")
            .font(.title)
        HStack(alignment: .top) {
            Text("Joshua Tree National Park")
                .font(.subheadline)
            Spacer()
            Text("California")
                .font(.subheadline)
        }
    }
    .padding()
        Spacer()

    }
  }
}                                                                                                  

Fichier B:

struct ContentView: View {
var body: some View {
    NavigationView {
        VStack {
            Text("Hello World")
            NavigationLink(destination: secondView()) {
                Text("Hit Me!")
                    .fontWeight(.semibold)
                    .font(.title)
                    .padding()
                    .foregroundColor(.white)
                    .background(LinearGradient(gradient: Gradient(colors: [Color(.white),Color(.blue)]), startPoint: .leading, endPoint: .trailing))
                    .cornerRadius(40)
        }
      }
    }
  }
}


0 commentaires

26
votes

J'ai fait un ViewModifier pour cela. Cela signifie également qu'il n'y a pas de barre de navigation. Vous pouvez l'appeler ainsi:

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()
                }
            }
        }
    }
}

Cela 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 d' import SwiftUI ):

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


9 commentaires

approche soignée, même si cela semblait casser mes vues préexistantes avec un style déjà appliqué.


très concis, soigné. meilleur


Bon travail. Une dernière chose, une chance de changer l'animation de navigation? Il était toujours de gauche à droite par défaut.


@sakiM De quelle manière l'animeriez-vous? C'est par défaut et une norme donc je l'ai juste laissé comme ça. Si vous voulez que cela vienne du bas, je suggérerais plutôt .sheet . Ne confondez pas les utilisateurs avec un comportement inattendu


Malheureusement, dans Xcode 12.2, cela fonctionne, mais met un petit rectangle gris au milieu de l'écran d'origine. Ce n'est donc plus viable.


@Plasma Cela semble très étrange. Pouvez-vous télécharger sur imgur et répondre avec un lien pour que je puisse voir?


@George_E ici vous allez .. le petit rect rond gris apparaît immédiatement après l'ajout de .navigate (à: MainPageView (), quand: $ willMoveToNextScreen) au bas de ma vue, si je commente cette ligne, le rect rond disparaît ... .. imgur.com/r4lblhn


@Plasma Essayez de l'utiliser dans un projet vierge. Cela ne me semble vraiment pas du tout lié. Cela pourrait être un problème avec les aperçus (essayez le simulateur), mais sinon, c'est probablement quelque chose dans votre code que vous avez accidentellement manqué. Cela ressemble presque à .redacted(reason: .placeholder) pour moi mais je ne suis pas sûr


@George_E après pas mal de tests, semble être un problème uniquement si la cible est tvOS, fonctionne bien sur IOS. Mais lorsqu'il est réglé sur tvOS, le rectangle gris est visible dans l'aperçu, le simulateur et sur un appareil réel.



1
votes

Je pense que la réponse de Jake est le moyen de base de NextView.

Et je pense que la manière ci-dessous est une manière simple, formelle et dynamique d'essayer, si vous avez vraiment besoin d'appuyer sur un BOUTON. D'après la vidéo de Paul Hudson , de 10'00 "à 12'00".

(devrait aller de 12'00 "à 15'00", si vous voulez accéder à différentes vues en appuyant sur différents boutons.) (devrait aller de 15'00 "à 16'00", si vous voulez aller à la deuxième vue et revenir automatiquement .) Et plus

Et voici l'exemple de code.

import SwiftUI

struct ContentView: View {

    @State var areYouGoingToSecondView: Bool // Step 2

    var body: some View {
        NavigationView{ // Step 1

            VStack {

                // Step 3
                NavigationLink(destination: YourSecondView(), isActive: $areYouGoingToSecondView) { EmptyView() }


                Text("Hello World")

                Button(action: {
                    self.areYouGoingToSecondView = true // Step 4

                }) {
                    Text("Do Something (Go To Second View)")
                    .font(.largeTitle)
                    .fontWeight(.ultraLight)
                }
            }
        }
    }
}


0 commentaires

6
votes

si vous ne voulez pas afficher la navigationView, vous pouvez la masquer 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 souhaitez le masquer en fonction des conditions, vous pouvez utiliser @State pour modifier la visibilité.


0 commentaires

0
votes

Nous pouvons utiliser le texte dans la navigation et le faire comme Button entrez la description de l'image ici http://g.recordit.co/CkIkjvikfu.gif

struct HomeContent: View {
    var body: some View {
        NavigationView{
            VStack {
                NavigationLink(
                destination: LoginContentView()) {
                    
                        
                           
                    Text("Login")
                        .font(.title)
                        .foregroundColor(Color.white)
                        .multilineTextAlignment(.center)
                        .frame(width: 300.0, height: 50.0)
                        .background(Color(UIColor.appLightBlue))
                   
                }
                
            }
        }
    }
}


0 commentaires

1
votes

Je pense que c'est la manière la plus simple et la plus claire. Utilisez fullScreenCover après l'outil d'interface utilisateur.

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


2 commentaires

Le problème avec cela est qu'il ne met pas de couleur d'arrière-plan pour le fullScreenCover


Intéressant, mais je vois aussi qu'il s'agit d'une fonctionnalité iOS 14.0 uniquement dans XCode.



0
votes

Code mis à jour SwiftUI 2.0

 var body: some View {
    NavigationView {
        navigationTitle("Me")
        Text("Hello, world!")
            .padding()
        NavigationLink(
            destination: DetailView(),
            label: {
                Text("Navigate")
            })
    }
}


1 commentaires

Je ne vois pas ce qui est différent avec ce code des autres réponses.