1

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):

enter image description here

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?

1 Answer 1

1

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)
        }
    }
}
Sign up to request clarification or add additional context in comments.

Comments

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.