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) } } } }
12 Réponses :
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") } } } } }
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?
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")) } } }
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")) }}
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") } } } } }
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") } } } }
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) } } } } }
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)
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.
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) } } } } }
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é.
Nous pouvons utiliser le texte dans la navigation et le faire comme Button 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)) } } } } }
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() })
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.
Code mis à jour SwiftUI 2.0
var body: some View { NavigationView { navigationTitle("Me") Text("Hello, world!") .padding() NavigationLink( destination: DetailView(), label: { Text("Navigate") }) } }
Je ne vois pas ce qui est différent avec ce code des autres réponses.