I am trying to accomplish a relatively simple task. I want to navigate from a root view -> intermediate view that captures input -> final view that displays input -> back to root view.
The solution I came up with uses the new NavigationPath and NavigationStack constructs and is partially derived from this stack overflow post: A complex Navigation with NavigationPath in SwiftUI
I created an enum with my views (NAV_ITEMS), then created a path of type NAV_ITEMS, and pushed onto that path when I wanted to go to the next view. A downfall of this solution is that I manage the state variable, called newRoomName, from the root view and pass it down as a binding to both child views, which seems wrong.
import SwiftUI
enum NAV_VIEWS {
case AddRoomName, AddRoomSuccess, addHomeName, addHomeNameSuccess
}
struct NavPathTestView: View {
@State var presentedViews = [NAV_VIEWS]()
@State var newRoomName: String = ""
var body: some View {
NavigationStack(path: $presentedViews) {
NavigationLink(value: NAV_VIEWS.AddRoomName) {
HStack {
Text("Add Room")
}.padding()
.foregroundColor(.white)
.background(Color.red)
.cornerRadius(40)
}
.navigationDestination(for: NAV_VIEWS.self) { i in
switch i {
case .AddRoomName:
RoomView(presentedViews: $presentedViews, newRoomName: $newRoomName)
case .AddRoomSuccess:
RoomSuccessView1(presentedViews: $presentedViews, newRoomName: $newRoomName)
case .addHomeName:
Text("add Home Name")
case .addHomeNameSuccess:
Text("Add Home Success")
}
}
.navigationTitle("Root Page")
}
}
}
struct RoomView: View {
@Binding var presentedViews : [NAV_VIEWS]
@Binding var newRoomName: String
var body: some View {
VStack() {
Text("Add Room Name")
Spacer()
TextField("My new Room", text: $newRoomName)
.padding()
.textInputAutocapitalization(.words)
.cornerRadius(20)
.onSubmit {
print("NewRoomName: \(newRoomName)")
}
Spacer()
Button (action: {
presentedViews.append(NAV_VIEWS.AddRoomSuccess)
})
{
HStack {
Text("Go to Success")
}.padding()
.foregroundColor(.white)
.background(Color.red)
.cornerRadius(40)
}
}
}
}
struct RoomSuccessView1: View {
@Binding var presentedViews : [NAV_VIEWS]
@Binding var newRoomName: String
var body: some View {
VStack {
Text("Room Success Page")
Spacer()
Text("The passed newRoomName: \(newRoomName)")
Spacer()
Button (action: {
presentedViews.removeLast(presentedViews.count)
})
{
HStack {
Text("Back To Root")
}.padding()
.foregroundColor(.white)
.background(Color.red)
.cornerRadius(40)
}
}
}
}
struct NavPathTestView_Previews: PreviewProvider {
static var previews: some View {
NavPathTestView()
}
}
Is there a better way to do this? Routing using navigationDestination on each child view caused path issues and animation issues with how screens came into the presentation.
For example, if I used a navigationDestination on each child view (child1 -> child2) then called RootView() from the child2 view to navigate back to root, it would return, but the next time that child1 was opened it would slide in from the left hand side of the screen, different than the normal slide in from the right.