web-dev-qa-db-fra.com

Comment supprimer l'espace de barre de navigation par défaut dans SwiftUI NavigationView

Je suis nouveau sur SwiftUI (comme la plupart des gens) et j'essaie de comprendre comment supprimer des espaces au-dessus d'une liste que j'ai incorporée dans une NavigationView

Dans cette image, vous pouvez voir qu'il y a un espace blanc au-dessus de la liste

Current Version

Ce que je veux accomplir c'est ceci

Ideal Version

J'ai essayé d'utiliser

.navigationBarHidden(true)

mais cela n'a apporté aucun changement notable.

je suis en train de configurer ma navigation

 NavigationView {
                FileBrowserView(jsonFromCall: URLRetrieve(URLtoFetch: applicationDelegate.apiURL))
                    .navigationBarHidden(true)
                }

où FileBrowserView est une vue avec une liste et des cellules définies comme ceci

List {
   Section(header: Text("Root")){
    FileCell(name: "Test", fileType: "JPG",fileDesc: "Test number 1")

                    FileCell(name: "Test 2", fileType: "txt",fileDesc: "Test number 2")
                    FileCell(name: "test3", fileType: "fasta", fileDesc: "")
}
}

Je veux noter que le but ultime ici est que vous serez en mesure de cliquer sur ces cellules pour naviguer plus profondément dans une arborescence de fichiers et donc d'afficher un bouton Retour sur la barre pour une navigation plus approfondie, mais je ne veux rien à la top en tant que tel lors de ma vue initiale.

40
Vapidant

Pour une raison quelconque, SwiftUI requiert que vous définissiez également .navigationBarTitle pour .navigationBarHidden pour fonctionner correctement.

NavigationView {
    FileBrowserView(jsonFromCall: URLRetrieve(URLtoFetch: applicationDelegate.apiURL))
        .navigationBarTitle("")
        .navigationBarHidden(true)
}

Mettre à jour

Comme @Peacemoon l'a souligné dans les commentaires, la barre de navigation reste masquée lorsque vous naviguez plus profondément dans la pile de navigation, que vous définissiez ou non navigationBarHidden sur false dans les vues suivantes. Comme je l'ai dit dans les commentaires, c'est soit le résultat d'une mauvaise mise en œuvre de la part d'Apple, soit simplement une documentation épouvantable (qui sait, il y a peut-être une façon "correcte" d'y parvenir).

Quoi qu'il en soit, j'ai trouvé une solution de contournement qui semble produire les résultats souhaités de l'affiche originale. J'hésite à le recommander car il semble inutilement hacky, mais sans aucun moyen simple de masquer et d'afficher la barre de navigation, c'est le mieux que je puisse faire.

Cet exemple utilise trois vues - View1 possède une barre de navigation masquée et View2 et View3 les deux ont des barres de navigation visibles avec des titres.

struct View1: View {
    @State var isNavigationBarHidden: Bool = true

    var body: some View {
        NavigationView {
            ZStack {
                Color.red
                NavigationLink("View 2", destination: View2(isNavigationBarHidden: self.$isNavigationBarHidden))
            }
            .navigationBarTitle("Hidden Title")
            .navigationBarHidden(self.isNavigationBarHidden)
            .onAppear {
                self.isNavigationBarHidden = true
            }
        }
    }
}

struct View2: View {
    @Binding var isNavigationBarHidden: Bool

    var body: some View {
        ZStack {
            Color.green
            NavigationLink("View 3", destination: View3())
        }
        .navigationBarTitle("Visible Title 1")
        .onAppear {
            self.isNavigationBarHidden = false
        }
    }
}

struct View3: View {
    var body: some View {
        Color.blue
            .navigationBarTitle("Visible Title 2")
    }
}

La définition de navigationBarHidden sur false sur des vues plus profondes dans la pile de navigation ne semble pas remplacer correctement la préférence de la vue qui avait initialement défini navigationBarHidden sur true, donc la seule solution de contournement que j'ai pu trouver était d'utiliser une liaison pour changer la préférence de la vue d'origine lorsqu'une nouvelle vue est poussée sur la pile de navigation.

Comme je l'ai dit, c'est une solution hacky, mais sans solution officielle d'Apple, c'est la meilleure que j'ai pu trouver.

60
graycampbell

Le but d'un NavigationView est d'ajouter la barre de navigation en haut de votre vue. Dans iOS, il existe 2 types de barres de navigation: grandes et standard.

enter image description here

Si vous ne voulez pas de barre de navigation:

FileBrowserView(jsonFromCall: URLRetrieve(URLtoFetch: applicationDelegate.apiURL))

Si vous voulez une grande barre de navigation (généralement utilisée pour vos vues de haut niveau):

NavigationView {
    FileBrowserView(jsonFromCall: URLRetrieve(URLtoFetch: applicationDelegate.apiURL))
    .navigationBarTitle(Text("Title"))
}

Si vous souhaitez une barre de navigation standard (en ligne) (généralement utilisée pour les vues de sous-niveau):

NavigationView {
    FileBrowserView(jsonFromCall: URLRetrieve(URLtoFetch: applicationDelegate.apiURL))
    .navigationBarTitle(Text("Title"), displayMode: .inline)
}

J'espère que cette réponse vous aidera.

Plus d'informations: Documentation Apple

8
TheFlow_

Il s'agit d'un bogue présent dans SwiftUI (toujours à partir de Xcode 11.2.1). J'ai écrit un ViewModifier pour résoudre ce problème, basé sur le code des réponses existantes:

public struct NavigationBarHider: ViewModifier {
    @State var isHidden: Bool = false

    public func body(content: Content) -> some View {
        content
            .navigationBarTitle("")
            .navigationBarHidden(isHidden)
            .onAppear { self.isHidden = true }
    }
}

extension View {
    public func hideNavigationBar() -> some View {
        modifier(NavigationBarHider())
    }
}
4
Vatsal Manot

Les modificateurs de vue ont simplifié la tâche:

//ViewModifiers.Swift

struct HiddenNavigationBar: ViewModifier {
    func body(content: Content) -> some View {
        content
        .navigationBarTitle("", displayMode: .inline)
        .navigationBarHidden(true)
    }
}

extension View {
    func hiddenNavigationBarStyle() -> some View {
        ModifiedContent(content: self, modifier: HiddenNavigationBar())
    }
}

Exemple: enter image description here

import SwiftUI

struct MyView: View {
    var body: some View {
        NavigationView {
            VStack {
                Spacer()
                HStack {  
                    Spacer()
                    Text("Hello World!")
                    Spacer()
                }
                Spacer()
            }
            .padding()
            .background(Color.green)
            //remove the default Navigation Bar space:
            .hiddenNavigationBarStyle()
        }
    }
}
3
Peter Kreinz

Pour moi, j'appliquais le .navigationBarTitle au NavigationView et non au List était le coupable. Cela fonctionne pour moi sur Xcode 11.2.1:

struct ContentView: View {
    var body: some View {
        NavigationView {
            List {
                NavigationLink(destination: DetailView()) {
                    Text("I'm a cell")
                }
            }.navigationBarTitle("Title", displayMode: .inline)
        }
    }
}

Navigation bar and list with no gap at the top

2
Genki

Vous pouvez étendre le protocole natif View comme ceci:

extension View {
    func hideNavigationBar() -> some View {
        self
            .navigationBarTitle("", displayMode: .inline)
            .navigationBarHidden(true)
    }
}

Appelez ensuite par exemple:

ZStack {
    *YOUR CONTENT*
}
.hideNavigationBar()
2
Hopreeeenjust

Pour moi, c'était parce que je poussais ma NavigationView à partir d'un existant. En effet, avoir l'un à l'intérieur de l'autre. Si vous venez d'une NavigationView, vous n'avez pas besoin d'en créer une à l'intérieur de la suivante comme vous l'avez déjà à l'intérieur d'une NavigatonView.

1
RyanTCB

Similaire à la réponse de @graycampbell mais un peu plus simple:

struct YourView: View {

    @State private var isNavigationBarHidden = true

    var body: some View {
        NavigationView {
            VStack {
                Text("This is the master view")
                NavigationLink("Details", destination: Text("These are the details"))
            }
                .navigationBarHidden(isNavigationBarHidden)
                .navigationBarTitle("Master")
                .onAppear {
                    self.isNavigationBarHidden = true
                }
                .onDisappear {
                    self.isNavigationBarHidden = false
                }
        }
    }
}

La définition du titre est nécessaire car il est affiché à côté du bouton de retour dans les vues vers lesquelles vous naviguez.

1
Fabian Streitel

J'ai vraiment adoré l'idée donnée par @ Vatsal Manot Pour créer un modificateur pour cela.
Suppression de la propriété isHidden de sa réponse, car je ne la trouve pas utile car le nom du modificateur lui-même suggère de masquer la barre de navigation.

// Hide navigation bar.
public struct NavigationBarHider: ViewModifier {

    public func body(content: Content) -> some View {
        content
            .navigationBarTitle("")
            .navigationBarHidden(true)
    }
}

extension View {
    public func hideNavigationBar() -> some View {
        modifier(NavigationBarHider())
    }
}
0
Kiran Jasvanee