swiftuinavigation

How to transition between two views without NavigationView


I am trying to transition from a main view to a sub view at the click of a button. I do not want to use NavigationView because it tries to add this awkward sidebar in the place where the button should be (what I want, what I get, code I used in place of a button).

NavigationView {
        NavigationLink (destination: CreateRoutineView(push: self.$push)) {
                Image(systemName: "pencil")
                    .resizable()
                    .scaledToFit()
                    .frame(height: 30)
        }
        .navigationBarTitle("")
        .navigationBarHidden(true)
}

I did find this stack overflow post that provides a brilliant example on how to do this but the example does not fit with my project quite right. With what I have now, I am able to toggle to the subview, but it appears on top of my main view. How can I adapt the solution provided to fit with my project?

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

var body: some View {
    
    ZStack {
        VStack {
            HStack{
                    
                Spacer()
                
                // Button used to navigate to subview
                Button {
                    push.toggle()
                } label: {
                    Image(systemName:"plus.circle")
                        .resizable()
                        .scaledToFit()
                        .frame(height: 30)
                }
                
            }
            .padding()
            .background(Color.gray)
            
            if push {
                CreateRoutineView(push: $push).transition(.asymmetric(insertion: .move(edge: .trailing), removal: .move(edge: .trailing)))
            }
        }
    }
    .padding()
}
}
#Preview {
    MainView()
}

struct SubView: View {
@Binding var push: Bool

var body: some View {
    ZStack {
        VStack {
            HStack {
                
                Spacer()

                Button {
                    self.push.toggle()
                } label: {
                    Text("Save")
                        .font(.title)
                }
                .padding()
            }
            .padding()
            .background(Color.gray)

        }
    }
    
}
}

#Preview {
    @Previewable @State var push: Bool = false
    CreateRoutineView(push: $push)
}

Solution

  • Move your if push { CreateRoutineView(push: $push)...} which I suspect is if push { SubView(push: $push)...}, outside your MainView VStack but still inside the ZStack, works for me.

    Example code:

    
    struct MainView: View {
        @State private var push = false
        
        var body: some View {
            ZStack {
                VStack {
                    HStack {
                        Spacer()
                        // Button used to navigate to subview
                        Button {
                            push.toggle()
                        } label: {
                            Image(systemName:"plus.circle")
                                .resizable()
                                .scaledToFit()
                                .frame(height: 30)
                        }
                    }
                    .padding()
                    .background(Color.gray)
                }
    
                if push {  // <--- here
                    SubView(push: $push)
                        .transition(.asymmetric(insertion: .move(edge: .trailing), removal: .move(edge: .trailing)))
                }
                
            }
            .padding()
        }
    }