Reputation: 51
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
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
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
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
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