skip to Main Content

How can one have a list where each item in the list contains a Link and a NavigationLink?

When putting the Link and NavigationLink next to each other in an HStack both get triggered wherever I tap on the row.

struct ContentView: View {

    var body: some View {
        NavigationView {
            List {
                HStack {
                    Link(
                        "Link",
                        destination: URL(string: "https://www.apple.com")!
                    )
                    NavigationLink(
                        "Other View",
                        destination: Text("Hello from other view"))
                }
            }
        }
    }
}

2

Answers


  1. Chosen as BEST ANSWER

    Based on shufflingb's answer:

    Replace the link with a non-tappable element and add a gesture handler to it.

    struct ContentView: View {
    
        @Environment(.openURL) private  var openURL
        let url = URL(string: "https://www.apple.com")
    
        var body: some View {
            NavigationView {
                List {
                    HStack {
    
                        Text("Link")
                            .foregroundColor(.accentColor)
                            .onTapGesture {
                                openURL(url!)
                            }
    
                        NavigationLink(
                            "Other View",
                            destination: Text("Hello from other view")
                        )
                    }
                }
            }
        }
    }
    

  2. Turns out the way Apple recommend to do this is to explicitly set the style on the Link button. e.g.

    struct ContentView: View {
    
        var body: some View {
            NavigationView {
                List {
                    HStack {
                        Link(
                            "Link",
                            destination: URL(string: "https://www.apple.com")!
                        )
                            .buttonStyle(.borderless) // <-- add this
                        NavigationLink(
                            "Other View",
                            destination: Text("Hello from other view"))
                    }
                }
            }
        }
    }
    

    Answer based on excellent notes over here https://swiftui-lab.com/random-lessons/. Do wish Apple would improve their SwiftUI docs!

    Previous, it worked, but don’t really recommend way of doing it by adding onTapGesture to the Link that explicity opens the URL. left below for context.

    struct ContentView: View {
       
        @Environment(.openURL) private  var openURL
        let url = URL(string: "https://www.apple.com")
        var body: some View {
            NavigationView {
                List {
                    HStack {
                        
                        Link(
                            "Link",
                            destination: url!
                        )
                        .onTapGesture {
                            print("Opening URL (url)")
                            openURL(url!)
                        }
                        
                        NavigationLink(
                            "Other View",
                            destination: Text("Hello from other view")
                        )
                    }
                }
            }
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search