21

I am trying to change a view without having something over it like when you used segue in swift. But the only solution I came up with is to have a navigation bar navigationBar or a popover.

struct view1: View {

    var body: some View{

        Button(action: {
//          go to view2``
        }) {
            Text("press")
        }

    }
}
struct view2: View {

    var body: some View{
       Text("yeay")

    }
}
1
  • 1
    Welcome to SO! If you could add a minimal, reproducible example to your question that will help it get answered a lot quicker and more accurately. Commented Oct 25, 2019 at 19:20

4 Answers 4

15

If you just want to hide the navigation bar it's easy:

import SwiftUI

struct View2: View {
    @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>

    var body: some View {
        VStack {
            Button(action: {
                self.presentationMode.wrappedValue.dismiss()
            }) {
                Text("POP")
            }
        }
        .navigationBarTitle("")
        .navigationBarBackButtonHidden(true)
        .navigationBarHidden(true)
    }
}

struct ContentView: View {
    var body: some View {
        NavigationView {
            NavigationLink(destination: View2()) {
                Text("PUSH")
                    .navigationBarTitle("")
                    .navigationBarHidden(true)
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

If you, instead, want to get rid of the NavigationView and NavigationLink views you have to implement your own custom navigation. It's a little more complicated. The following is just a simple example of a push/pop transition between two views.

import SwiftUI

struct View2: View {
    @Binding var push: Bool

    var body: some View {
        ZStack {
            Color.yellow
            Button(action: {
                withAnimation(.easeOut(duration: 0.3)) {
                    self.push.toggle()
                }
            }) {
                Text("POP")
            }
        }
        .edgesIgnoringSafeArea(.all)
    }
}

struct View1: View {
    @Binding var push: Bool

    var body: some View {
        ZStack {
            Color.green
            Button(action: {
                withAnimation(.easeOut(duration: 0.3)) {
                    self.push.toggle()
                }
            }) {
                Text("PUSH")
            }
        }
        .edgesIgnoringSafeArea(.all)
    }
}

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

    var body: some View {
        ZStack {
            if !push {
                View1(push: $push)
                    .transition(.asymmetric(insertion: .move(edge: .leading), removal: .move(edge: .leading)))
            }

            if push {
                View2(push: $push)
                    .transition(.asymmetric(insertion: .move(edge: .trailing), removal: .move(edge: .trailing)))
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
  static var previews: some View {
    ContentView()
  }
} 
Sign up to request clarification or add additional context in comments.

1 Comment

What if I wanted to switch to multiple views, not just View1 and View2?
6

Anyone coming to this later might find this to be of interest; in short, shove a hunk of data into @environment, tickle that with a button push in whatever view you want, and since it's at the very top of the overall application stack, it forces a redraw, which acts like a full view navigation, without the potential lost memory and orphaned or lost objects of the whole push/pop navigation view silliness.

It's still a little more "single page app"-ey than I'd like, but since SwiftUI is so crippled in its navigation thoroughness, it'll do nicely.

Not my site, not my link, not my tutorial, and it's buried way down in the list of hits when searching, which is a shame; this is the closest to what many are looking for. IMO, this should be baked into SwiftUI as a first class operation, and made less workaround-ey.

https://blckbirds.com/post/how-to-navigate-between-views-in-swiftui-by-using-an-environmentobject/

1 Comment

Link seems to be broken
3

You can also do this completely without NavigationView. Take a look at the following example:

struct MainView: View
{
    @State private var showView = "LoginView"
    
    var body: some View
    {
        switch showView
        {
        case "LoginView":
            Text("Please login.")
            Button("Login")
            {
                showView = "NormalView"
            }
        case "NormalView":
            Text("This is youre NormalView!")
            Button("Next view")
            {
                showView = "NextView"
            }
        case "NextView":
            Text("This is the NextView")
            Button("Back")
            {
                showView = "NormalView"
            }
        default:
            Text("Default") // you should never reach this
        }
    }
}

Perhaps not the best code practice, but it solves your problem.

2 Comments

I'm new to Swift, but I don't see anything wrong with this solution. Why do you say it might not be good practice?
As your views get bigger its probably hard or at least confusing to maintain in the right state. One single typo and you will end in the default case. Also I haven't managed to get it to work with proper transition animations.
0

I think this not best way but it's easy

struct ContentView: View {

@State var gotoDetail3:Bool = false

var body: some View {
    NavigationView{
        ZStack{
            VStack {
                // Normal NavigationLink
                NavigationLink {
                    Text("Detail......")
                } label: {
                    Text("goto..")
                }
                
                //use for change state
                Button {
                    gotoDetail3.toggle()
                } label: {
                    Text("goto33333")
                }
            }// End VStack
            
            
            // Hide Navigation Link
            NavigationLink(
                LocalizedStringKey("123"), destination: Text("Subsequent View"),
                isActive: $gotoDetail3)
                .hidden()
        }
        
    }
}
    
}

1 Comment

Eventhough, you can hide the NavigationLink but user can swipe right to go back to previous view.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.