Présentez une nouvelle vue dans SwiftUI


11

Je veux cliquer sur un bouton puis présenter une nouvelle vue comme present modallydans UIKit entrez la description de l'image ici

J'ai déjà vu " Comment présenter une nouvelle vue à l'aide de feuilles ", mais je ne veux pas la joindre à la vue principale en tant que feuille modale.

Et je ne veux pas l'utiliser NavigationLink, car je ne veux pas qu'une nouvelle vue et une ancienne vue aient une relation de navigation.

Merci de votre aide...


Pourquoi ne voulez-vous pas l'attacher à la vue principale en tant que feuille modale? C'est une méthode standard même en UIKit. Avez-vous une raison particulière?
Mojtaba Hosseini

J'essaie d'expliquer mes pensées ... S'il y a quelque chose qui ne va pas, veuillez me corriger.
CH Wing

Les applications ont 3 vues, 1: page de connexion 2: page TableView 3: page TableDetail, page TableView et page TableDetail est une relation de navigation. Une fois la connexion présentée à la page TableView, la page TableView n'a aucune relation avec la page de connexion après la connexion
CH Wing

Vous en avez donc besoin pour avoir fullscreenraison?
Mojtaba Hosseini

oui! je veuxfullscreen
CH Wing

Réponses:


12

Pour afficher un modal (style iOS 13)

Vous avez juste besoin d'un simple sheetavec la possibilité de se rejeter:

struct ModalView: View {
    @Binding var presentedAsModal: Bool
    var body: some View {
        Button("dismiss") { self.presentedAsModal = false }
    }
}

Et présentez-le comme:

struct ContentView: View {
    @State var presentingModal = false

    var body: some View {
        Button("Present") { self.presentingModal = true }
        .sheet(isPresented: $presentingModal) { ModalView(presentedAsModal: self.$presentingModal) }
    }
}

Notez que j'ai transmis le presentingModalau modal afin que vous puissiez le supprimer du modal lui-même, mais vous pouvez vous en débarrasser.


Pour le rendre VRAIMENT présent fullscreen(pas seulement visuellement)

Vous devez accéder au ViewController. Vous avez donc besoin de conteneurs d'assistance et de choses d'environnement:

struct ViewControllerHolder {
    weak var value: UIViewController?
}

struct ViewControllerKey: EnvironmentKey {
    static var defaultValue: ViewControllerHolder {
        return ViewControllerHolder(value: UIApplication.shared.windows.first?.rootViewController)

    }
}

extension EnvironmentValues {
    var viewController: UIViewController? {
        get { return self[ViewControllerKey.self].value }
        set { self[ViewControllerKey.self].value = newValue }
    }
}

Ensuite, vous devez utiliser implémenter cette extension:

extension UIViewController {
    func present<Content: View>(style: UIModalPresentationStyle = .automatic, @ViewBuilder builder: () -> Content) {
        let toPresent = UIHostingController(rootView: AnyView(EmptyView()))
        toPresent.modalPresentationStyle = style
        toPresent.rootView = AnyView(
            builder()
                .environment(\.viewController, toPresent)
        )
        self.present(toPresent, animated: true, completion: nil)
    }
}

finalement

vous pouvez le faire fullscreencomme:

struct ContentView: View {
    @Environment(\.viewController) private var viewControllerHolder: UIViewController?

    var body: some View {
        Button("Login") {
            self.viewControllerHolder?.present(style: .fullScreen) {
                Text("Main") // Or any other view you like
            }
        }
    }
}

génial! merci pour votre solution détaillée
CH Wing

J'obtiens cette erreur dans l'encapsuleur de propriété d'environnement: Impossible de convertir la valeur de type 'Environment <UIViewController?>' En type spécifié 'UIViewController'
jsbeginnerNodeJS

Il doit être géré par défaut, mais essayez d'y ajouter ?à la fin de la ligne. @jsbeginnerNodeJS
Mojtaba Hosseini

Je reçois cette erreur de la console: `` `Avertissement: tentative de présenter <_TtGC7SwiftUI19UIHostingControllerVS_7AnyView_: 0x7fafd2641d30> sur <_TtGC7SwiftUI19UIHostingControllerVS_7AnyView_: 0x7fafd2611bd0> dont la vue est pas dans la hiérarchie de la fenêtre` ``!
jsbeginnerNodeJS

comment le rejetez-vous?
gabrielapittari

0

Voici une vue simple à sens unique. C'est très simple.

        struct ChildView: View{
           private  let colors: [Color] = [.red, .yellow,.green,.white]
           @Binding var index : Int
           var body: some View {
           let next = (self.index+1)  % MyContainer.totalChildren
             return   ZStack{
                    colors[self.index  % colors.count]
                     Button("myNextView \(next)   ", action: {
                    withAnimation{
                        self.index = next
                    }
                    }
                )}.transition(.asymmetric(insertion: .move(edge: .trailing)  , removal:  .move(edge: .leading)  ))
            }
        }

        struct MyContainer: View {
            static var totalChildren = 10
            @State private var value: Int = 0
            var body: some View {
                    HStack{
                        ForEach(0..<(Self.totalChildren) ) { index in
                            Group{
                            if    index == self.value {
                                ChildView(index:  self.$value)
                                }}
                            }
                }
                }
        }

-1

Avertissement: ci-dessous n'est pas vraiment comme un "modal natif", ni se comporter ni se sentir et se sentir, mais si quelqu'un a besoin d'une transition personnalisée d'une vue par rapport à une autre, ne rendant active que la première, l'approche suivante pourrait être utile.

Donc, si vous vous attendez à quelque chose comme ce qui suit

modal SwiftUI personnalisé

Voici un code simple pour démo l'approche (de l'animation corse & les paramètres de transition peuvent être modifiés à souhait)

struct ModalView : View {
    @Binding var activeModal: Bool
    var body : some View {
        VStack {
            Button(action: {
                withAnimation(.easeInOut(duration: 0.3)) {
                    self.activeModal = false
                }
            }) {
                Text("Hide modal")
            }
            Text("Modal View")
        }
        .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .center)
        .background(Color.green)
    }
}

struct MainView : View {
    @Binding var activeModal: Bool
    var body : some View {
        VStack {
            Button(action: {
                withAnimation(.easeInOut(duration: 0.3)) {
                    self.activeModal = true
                }
            }) {
                Text("Show modal")
            }
            Text("Main View")
        }
        .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .center)
        .background(Color.yellow)
    }
}

struct ModalContainer: View {
    @State var showingModal = false
    var body: some View {
        ZStack {
            MainView(activeModal: $showingModal)
                .allowsHitTesting(!showingModal)
            if showingModal {
                ModalView(activeModal: $showingModal)
                    .transition(.move(edge: .bottom))
                    .zIndex(1)
            }
        }
    }
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.