Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using NavigationLink in Menu (SwiftUI)

Tags:

Can you use a NavigationLink as a Menu's item in swiftUI?

It seems to do just nothing:

Menu {
   NavigationLink(destination: Text("test1")) {
       Text("item1")
   }
   NavigationLink(destination: Text("test2")) {
       Text("item2")
   }
} label: {
   Text("open menu")
}

In case it is meant to not work as tried above, is there an alternative way of achiving the intended reult?

like image 916
lenny Avatar asked Nov 15 '20 13:11

lenny


People also ask

How does NavigationLink work SwiftUI?

NavigationLink in SwiftUI allows pushing a new destination view on a navigation controller. You can use NavigationLink in a list or decide to push a view programmatically. The latter enables you to trigger a new screen from a different location in your view.

What is label in NavigationLink?

Presenting a destination view Creates a navigation link that presents a destination view, with a text label that the link generates from a title string. Available when Label is Text and Destination conforms to View . init(destination: () -> Destination, label: () -> Label)

How does NavigationView work in SwiftUI?

You see, navigation views let us display new screens of content by sliding them in from the right edge. Each screen can have its own title, and it's the job of SwiftUI to make sure that title is shown in the navigation view at all times – you'll see the old title animate away, while the new title animates in.


2 Answers

NavigationLink should be inside NavigationView hierarchy. The Menu is outside navigation view, so put buttons inside menu which activate navigation link placed inside navigation view, eg. hidden in background.

Here is a demo of possible approach (tested with Xcode 12.1 / iOS 14.1)

demo

struct DemoNavigateFromMenu: View {
    @State private var navigateTo = ""
    @State private var isActive = false
    var body: some View {
        NavigationView {
            Menu {
                Button("item1") {
                    self.navigateTo = "test1"
                    self.isActive = true
                }
                Button("item2") {
                    self.navigateTo = "test2"
                    self.isActive = true
                }
            } label: {
                Text("open menu")
            }
            .background(
                NavigationLink(destination: Text(self.navigateTo), isActive: $isActive) {
                    EmptyView()
                })
        }
    }
}
like image 101
Asperi Avatar answered Sep 30 '22 15:09

Asperi


I can say that Asperi's answer is great solution. It helped a lot. But we need a custom view to hold a reference inside the destination property right? not a string.

@State var navigateTo: AnyView?
@State var isNavigationActive = false

We can hold a reference AnyView type and then call the view like this:

Menu {
    Button {
        navigateTo = AnyView(CreateItemView())
        isNavigationActive = true
    } label: {
        Label("Create an Item", systemImage: "doc")
    }
    
    Button {
        navigateTo = AnyView(CreateItemView())
        isNavigationActive = true
    } label: {
        Label("Create a category", systemImage: "folder")
    }
} label: {
    Label("Add", systemImage: "plus")
}

For more detail please see this post: https://developer.apple.com/forums/thread/119583

like image 42
fatihios Avatar answered Sep 30 '22 16:09

fatihios