iosswiftswiftuiios-navigationview

SwiftUI Navigation Bar doesn't disappear


I have a NavigationView where I set the .navigationBarHidden(true) in my SplashScreen. Here it correctly does not display, however when I go to the next screen the NavigationView bar appears. How can i properly hide the navigation bar? The background does also not properly display.

View

struct EventsScreen: View {

    var eventsRepository: EventsRepository

    @State
    var currentPage: Int = 0
    @State
    private var searchTerm : String = ""


    func getEventSections() -> [EventSection] {
        eventsRepository.fetchEventSections()
    }

    func getViewControllers() -> [UIHostingController<EventFeatureView>] {
        return eventsRepository.fetchFeaturedEvents().map({ event in
            UIHostingController(rootView: EventFeatureView(event: event))
        })
    }
    var body: some View {
        NavigationView {
            List {
                ZStack(alignment: .top) {

                    EventViewController(controllers: self.getViewControllers(), currentPage: self.$currentPage)
                    VStack {
                        SearchBar(text: $searchTerm)
                            .padding(EdgeInsets.init(top: 16, leading: 16, bottom: 0, trailing: 16))
                        HStack {
                            Spacer()
                            Chip(text: "Dates", action:  {
                                //TODO filter on dates
                            })
                            Chip(text:"Type", action: {
                                //TODO filter event type
                            })
                            Chip(text: "Points", action: {
                                //TODO filter points
                            })
                            Spacer()
                        }
                    }
                }.listRowInsets(EdgeInsets())
                    .frame(height: 600)
                ForEach(self.getEventSections()) { section in
                    EventSectionView(eventSection: section)
                }
            }
        }
        .background(LinearGradient(gradient: Gradient(colors: [.black, ColorTheme.brandPurple.color]), startPoint: .top, endPoint: .bottom))
        .navigationBarTitle(Text("Events"), displayMode: .inline)
    .navigationBarHidden(true)
    }
}

Solution

  • You can set .navigationBarHidden(true) for the child View being presented within the NavigationView. I'm not sure what the next screen View looks like, but here's something I would try:

    struct NextScreen: View {
        var body: some View {
            Group {
                // existing body content
            }
            .background(LinearGradient(gradient: Gradient(colors: [.black, ColorTheme.brandPurple.color]), startPoint: .top, endPoint: .bottom))
            .navigationBarTitle(Text("Next Screen"), displayMode: .inline)
            .navigationBarHidden(true)
        }
    }
    

    The Group is just in case your body content isn't all wrapped in a View (e.g. VStack, List, etc.) of some kind.

    It might help to think about it like this:

    NavigationView will typically inherit .navigationBarHidden() from its child views. However, since .navigationBarHidden() and .background() are explicitly defined outside of the NavigationView in EventsScreen, they happen to work their ways down and apply to the child views in EventsScreen as well (unless those views have their own explicitly defined properties).

    While the NextScreen View is still presented within the NavigationView, the NextScreen is initialized with its own default properties, like background color. Once the app navigates/updates to NextScreen, the properties of NextScreen will take precedent, including the default of .navigationBarHidden(false), and likely the system background color. It's about which View (and its properties) will take precedent, and SwiftUI tends to give first dibs to the children, and broadening from there (provided that the scope of a given property applies to its parent views).

    So in summary, those defaults must be explicitly overridden in every View that appears within the NavigationView, if you want them to remain changed.