Adrian Le Roy Devezin
Adrian Le Roy Devezin

Reputation: 843

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

Upvotes: 1

Views: 2909

Answers (3)

Eldar
Eldar

Reputation: 554

You need to use your code like this:

var body: some View {
    NavigationView {
        ...
        .navigationBarTitle(Text("Events"), displayMode: .inline)
        .navigationBarHidden(true)
    }
    // that means only show one view at a time no matter what device I'm working
    .navigationViewStyle(StackNavigationViewStyle())
}

You can bind navigationBarHidden to variable, so that you can change the value under certain conditions. Like this: .navigationBarHidden($onOff)

Upvotes: 0

enordlund
enordlund

Reputation: 71

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.

Upvotes: 1

Asperi
Asperi

Reputation: 258345

Here is what SDK says:

/// Hides the navigation bar for this view.
///
/// This modifier only takes effect when this view is inside of and visible
/// within a `NavigationView`.
///
/// - Parameters:
///     - hidden: A Boolean value that indicates whether to hide the
///       navigation bar.
@available(OSX, unavailable)
public func navigationBarHidden(_ hidden: Bool) -> some View

so, you have to set it to false for every top view showing in NavigationView during navigation, otherwise it will be shown as you observe.

Upvotes: 0

Related Questions