You should only use one NavigationView
within your app. For example, at your Home screen of the app?
The NavigationLink
directs your users to a new view that should not have a NavigationView
view. Adding two NavigationView
s and linking them together will cause the behaviour you're describing by pushing one NavigationView
into another shrinking all other views (and themselves) inside.
Try taking all NavigationView
components away from all other views except your main/root view.
For example:
struct ROOT_VIEW: View {
var body: some View {
NavigationView {
VStack {
NavigationLink(destination: SECONDVIEW()) {
Text("Show Detail View")
}.navigationBarTitle("ROOT VIEW")
}
}
}
}
Link with second view (all other views):
struct SECOND_VIEW: View {
var body: some View {
VStack {
Text("This is the second view")
}.navigationBarTitle("ROOT VIEW", display: .inline)
}
}
}
Only adding .navigationBarTitle("ROOT VIEW", display: .inline)
to your second view allows a title to appear at the top (with one back button). You can also add buttons inside each title bar with:
.navigationBarItems(leading:
// FAR LEFT SIDE OF THE TITLE BAR
HStack {
Button(action: {// action goes here}) {
Image(systemName: "plus")
.font(.largeTitle)
}.foregroundColor(.pink)
}, trailing:
// FAR RIGHT SIDE OF THE TITLE BAR
HStack {
Button(action: { //action goes here}) {
Image(systemName: "plus")
.font(.largeTitle)
}.foregroundColor(.blue)
})
Another Option:
You can direct users between your app without using NavigationViews
. You can use simple Boolean states
.
For example, say you had a root view screen, and there were three buttons on the screen, one for logging in, one for registering and one for restting a password, each with their own views. You would only show one view based on a boolean value:
struct ROOT_VIEW: View {
@State var showLogin = true // This will be the default view that gets showed as its default to true
@State var showRegister = false
@State var showPasswordReset = false
var body: some View {
VStack{
if showLogin{
LoginView(showLogin: $showLogin, showRegister: $showRegister)
}
if showRegister{
RegisterView()
}
if showPasswordReset{
PasswordResetView()
}
}
}
}
struct LoginView: View {
@Binding var showLogin: Bool
@Binding var showRegister: Bool
var body: some View {
VStack{
Button(action: {
// Change two bool values to switch to register view (turning off login view and turning on reigster view)
showLogin.toggle()
showRegister.toggle()
}) {
Text("Show Register")
}.foregroundColor(.pink)
}
}
}
You would do this to all views that you want the user to go to (obviously). Say you only wanted the RegisterView
to only be able to go to the LoginView
and vice versa, you'd only need to provide the RegisterView
with the the showLogin
and showRegister
binding bools in the root view as shown:
RegisterView(showLogin: $showLogin, showRegister: $showRegister)
Make sure in your register view, you don't use a normal @State
you use a @Binding
to sync all Boolean values across views.