I have a safe area inset view that is placed on my NavigationStack
so that acts as a bottom bar across all pushed views. However, in the safe area inset view, there are button which I'd like to push views onto the stack. The NavigationLink
is greyed out though since it is outside of a NavigationStack
.
This is what my code looks like:
NavigationStack {
VStack {
Image(systemName: "globe")
Text("Hello, world!")
}
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
NavigationLink("Button 1") {
Text("Screen 1")
}
}
ToolbarItem(placement: .navigationBarTrailing) {
NavigationLink("Button 2") {
Text("Screen 2")
}
}
}
}
.safeAreaInset(edge: .bottom, spacing: 0) {
HStack {
NavigationLink("Button 1") {
Text("Screen 1")
}
.frame(minWidth: 0, maxWidth: .infinity)
NavigationLink("Button 2") {
Text("Screen 2")
}
.frame(minWidth: 0, maxWidth: .infinity)
}
.padding()
.background(.regularMaterial)
}
It behaves in a way where the bottom view does indeed stick across all pushed views, but the buttons there do not do anything (the ones in the top navigation bar work properly though):
How can I get the buttons in the bottom safe area inset to navigation to different screens while still keeping it on the NavigationStack
level since I do not want to place this bottom overlay code on each sub view?
You can use programmatic navigation with NavigationStack
:
The state var navigationPath
holds the active path and you can change it either with NavigationLink(value:)
or by setting it directly (like in the safe area buttons).
struct ContentView: View {
// holds the active navigation path
@State private var navigationPath: [Int] = []
var body: some View {
NavigationStack(path: $navigationPath ) {
VStack {
Image(systemName: "globe")
Text("Hello, world!")
}
// defines destinations of path
.navigationDestination(for: Int.self, destination: { value in
switch value {
case 1: Text("Screen 1")
case 2: Text("Screen 2")
default: Text("unknown view")
}
})
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
NavigationLink("Button 1", value: 1)
}
ToolbarItem(placement: .navigationBarTrailing) {
NavigationLink("Button 2", value: 2)
}
}
}
.safeAreaInset(edge: .bottom, spacing: 0) {
HStack {
Button("Button 1") {
navigationPath = [1]
// or if you want to extend the path:
// navigationPath.append(1)
}
.frame(maxWidth: .infinity)
Button("Button 2") {
navigationPath = [2]
// or if you want to extend the path:
// navigationPath.append(2)
}
.frame(maxWidth: .infinity)
}
.padding()
.background(.regularMaterial)
}
}
}