MustafaAlMarzooq
MustafaAlMarzooq

Reputation: 51

hide Navigation Bar only on first page - Swift UI

My app running on Swift UI, and my main page is Home(), In the home page there is NavigationView and NavigationLink(destination: SaveThePlanet()), I have hide the Navigation View on the main page "Home", its also hide in SaveThePlanet(). How can I unhide the navigation back button in the SaveThePlanet() page?

import SwiftUI

struct Home: View {

    @State var show = false
    @State var showSaveThePlanet = false
    var body: some View {
        NavigationView {
            ZStack {
                Color.gray
                ContentView()
                    .blur(radius: show ? 10 : 0)
                    .scaleEffect(show ? 0.90 : 1)
                    .blur(radius: showSaveThePlanet ? 10 : 0)
                    .scaleEffect(showSaveThePlanet ? 0.90 : 1)
                    .animation(.default)

                leftIcon(show: $show)
                    .offset(x: 0, y: showSaveThePlanet ? 300 : 70)
                    .scaleEffect(show ? 0.90 : 1)
                    .blur(radius: show ? 10 : 0)
                    .animation(.easeInOut)

                SaveThePlanet()
                    .background(Color("Bg"))
                    .cornerRadius(10)
                    .shadow(color: Color("Green-Sh"), radius: 10, x: 0, y: 0)
                    .animation(.spring())
                    .offset(y: showSaveThePlanet ? 120 : UIScreen.main.bounds.height)
                    .padding()

                rightIcon(show: $showSaveThePlanet)
                    .offset(x: 0, y: 70)
                    .animation(.easeInOut)
                    .scaleEffect(show ? 0.90 : 1)
                    .blur(radius: show ? 10 : 0)
                    .opacity(showSaveThePlanet ? 0 : 1)


                rightIconClose(show: $showSaveThePlanet)
                    .offset(x: 0, y: 70)
                    .animation(.easeInOut)
                    .scaleEffect(show ? 0.90 : 1)
                    .blur(radius: show ? 10 : 0)
                    .opacity(showSaveThePlanet ? 1 : 0)

                MenuView(show: $show)
            }
            .edgesIgnoringSafeArea(.all)
            .navigationBarTitle("Home")
            .navigationBarHidden(true)
            .navigationBarBackButtonHidden(false)

        }
    }
}

Upvotes: 5

Views: 5143

Answers (4)

L_Cleo
L_Cleo

Reputation: 1527

I'm answering because I think the solution nowadays is pretty easier. So for people having the same problem just add a

.navigationBarHidden(true)

on your Home() component and you should be fine. This solution works for sure in Swift 5.5, there is to do the onAppear and onDisappear trick of the other answers. It will hide only the navigation bar on the view you specified

Upvotes: 1

Mantas Skeiverys
Mantas Skeiverys

Reputation: 141

Best way that I found is toggling the navBarHidden in destination views. This way incomplete swipe to pop gestures will not remove the navigation bar.

So in your main view you would write

@State private var navBarHidden = true

var body: some View {
NavigationView {
    NavigationLink(
        destination: DetailView(navBarHidden: self.$navBarHidden)
    ) {
        Text("Go to detail view")
    }
}
.navigationBarTitle("")
.navigationBarHidden(self.navBarHidden)
}

And in your destination view:

@Binding var navBarHidden : Bool
var body: some View {
Text("Hello Detail View!")
    .navigationBarTitle("Detail")
    .onAppear {
        self.navBarHidden = false
    }
    .onDisappear {
        self.navBarHidden = true
    }
}

Upvotes: -1

Luke Smith
Luke Smith

Reputation: 1320

What worked for me : have an @State property on your first view, that determines whether or not you can show the navigation bar. Then pass that property on to all subsequent views via @Binding, so that it is the 'single source of truth' for whether or not the navigation bar should show.

@State private var navBarHidden = false

Then on your main view, reference that property for the navBarHidden property, and set the title. Also add an onAppear closure, which will set that hidden property for when this view re-appears, ie if we pop back here from a detail view.

var body: some View {
    NavigationView {
        NavigationLink(
            destination: DetailView(navBarHidden: self.$navBarHidden)
        ) {
            Text("Go to detail view")
        }
    }
    .navigationBarTitle("")
    .navigationBarHidden(self.navBarHidden)
    .onAppear(perform: {
        self.navBarHidden = true
    })
}

Then on a subsequent detail view, pass that navBarHidden property on as an @Binding (its passed in above)

@Binding var navBarHidden : Bool

var body: some View {
    Text("Hello Detail View!")
        .navigationBarTitle("Detail")
        .onAppear() {
            self.navBarHidden = false
        }

}

And when the onAppear() is called above in the detail view, it sets that original property to false for hidden, which shows the nav bar. And when you click back to return to the home view, the onAppear() of the home view is called again, which sets it back to hidden = true.

Upvotes: 10

John M.
John M.

Reputation: 9473

It's a little hard to tell based on the code you've posted, but it looks like you are trying to present a view that slides up from the bottom when showSaveThePlanet is true, and also show the navigation bar only when that view appears.

This can be accomplished by setting .navigationBarHidden(!showSaveThePlanet) anywhere in your body property. Note that your code does not use NavigationLink anywhere to push a new view onto the NavigationView stack, so you would not get a back button. You can add your own button to dismiss the sheet using .navigationBarItems(leading:)

Here is a simplified example showing what I mean.

struct ContentView: View {
    @State private var detailShowing = false

    var body: some View {
        NavigationView {
            ZStack(alignment: Alignment(horizontal: .center, vertical: .top)) {
                Color.gray.edgesIgnoringSafeArea(.all)

                // A card-like view that is initially offscreen,
                // and slides on when detailShowing == true
                DetailView()
                    .offset(x: 0, y: detailShowing ? 120 : UIScreen.main.bounds.height)
                    .animation(.spring())

                // Just here to change state
                Button("Toggle") {
                        self.detailShowing.toggle()
                }
                .padding()
                .offset(x: 0, y: detailShowing ? 0 : 44)
                .animation(.none)
            }
            // This is the key modifier
            .navigationBarHidden(!detailShowing)
            .navigationBarTitle("Detail View", displayMode: .inline)
            .navigationBarItems(leading: Button("Close") {
                self.detailShowing = false
            })
        }
    }
}

struct DetailView: View {
    var body: some View {
        ZStack(alignment: Alignment(horizontal: .center, vertical: .top)) {
            RoundedRectangle(cornerRadius: 15).fill(Color.secondary).frame(width: 300, height: 500)
            Text("Detail Content")
                .padding()
        }
    }
}

Upvotes: -1

Related Questions