skip to Main Content

I am trying to remove the chevron that appears on the right of the screen with a navigationLink that contains a view. This is my code below:

        NavigationView {
        List {
             NavigationLink(destination: DynamicList()) {
                  ResultCard()
             }
      ...
      }

Other answers on Stack Overflow have recommended using something like the below:

NavigationLink(...)
   .opacity(0)

However, this doesn’t work in my case since bringing the opacity down to 0 also removes the view that I am trying to display. This is also the case with ‘.hidden’. I’ve searched everywhere and the only somewhat working solution I could find was to alter the padding in order to ‘push’ the chevron off of the side, but this is a poor solution since the ‘ResultCard’ view will appear wonky/off-centre on different display sizes.

Perhaps it isn’t possible to remove the chevron – and if this is the case, is there any other way I can allow the user to tap the ‘ResultCard’ view and be taken to a new page, that isn’t through a navigation link?

I’m banging my head on the wall so any ideas are very much appreciated.

4

Answers


  1. You can use an .overlay on your label view with a NavigationLink with an EmptyView() set as its label:

    
    struct ContentView : View {
        var body: some View {
            NavigationView {
                List {
                    NavigationLink("Link 1", destination: Text("Hi"))
                    Text("Test")
                        .overlay(NavigationLink(destination: Text("Test"), label: {
                            EmptyView()
                        }))
                }
            }
        }
    }
    
    

    Example of overlay navigation

    Update:
    Another solution, which seems to work with other types of Views besides Text:

    struct ContentView : View {
        @State private var linkActive = false
        
        var body: some View {
            NavigationView {
                List {
                    NavigationLink("Link 1", destination: Text("Hi"))
                    Button(action: { linkActive = true }) {
                        Image(systemName: "pencil")
                    }.overlay(VStack {
                        if linkActive {
                            NavigationLink(destination: Text("Test"), isActive: $linkActive) {
                                EmptyView()
                            }.opacity(0)
                        }
                    })
                }
            }
        }
    }
    
    
    Login or Signup to reply.
  2. Here are two alternative variations using .background():

    // Replicate the iPhone Favorites tab with the info button
    // - Compose a button to link from a NavigationView to a next view
    // - Use this when you want to hide the navigation chevron decoration
    // - and/or to have a button trigger the link
    
    struct NavigationLinkButton<Destination: View, Label: View>: View {
        @Binding var selectedID: String?
        @State var rowID: String
        @ViewBuilder var destination: () -> Destination
        @ViewBuilder var label: () -> Label
    
        var body: some View {
            HStack {
                Spacer()
                Button {
                    selectedID = rowID
                } label: {
                    label()
                }
                .buttonStyle(.plain) // prevent List from processing *all* buttons in the row
                .background {
                    NavigationLink("", tag: rowID, selection: $selectedID) {
                        destination()
                    }
                    .hidden()
                }
            }
        }
    }
    
    // Replicate the iOS Spotlight search for contacts with action buttons
    // - Compose a list row to link from a NavigationView to a next view
    // - Use this when you want to hide the navigation chevron decoration
    // - and add action buttons
    
    struct NavigationLinkRowHidingChevron<Destination: View, Label: View>: View {
        @Binding var selectedID: String?
        @State var rowID: String
        @ViewBuilder var destination: () -> Destination
        @ViewBuilder var label: () -> Label
    
        var body: some View {
            ZStack {
                // Transparent button to capture taps across the entire row
                Button("") {
                    selectedID = rowID
                }
                label()
            }
            .background {
                NavigationLink("", tag: rowID, selection: $selectedID) {
                    destination()
                }
                .hidden()
            }
        }
    }
    
    // Example Usages
    //
    // @State private var selectedID: String?
    // @State private var editMode: EditMode = .inactive
    //
    // ... and then in the body:
    // List {
    //    ForEach(items) { item in
    //        row(for: item)
    //            .swipeActions(edge: .leading, allowsFullSwipe: true) {
    //                ...
    //            }
    //            .contextMenu {
    //                ...
    //            }
    //            .onDrag({
    //                ...
    //            })
    //            // Overlay so that a tap on the entire row will work except for these buttons
    //            .overlay {
    //                // Hide info button just as with Phone Favorites edit button
    //                if editMode == .inactive {
    //                    NavigationLinkHidingChevron(selectedID: $selectedID, rowID: item.id) {
    //                        // Destination view such as Detail(for: item)
    //                    } label: {
    //                        // Button to activate nav link such as an 􀅴 button
    //                    }
    //                }
    //            }
    //    }
    //    .onDelete(perform: deleteItems)
    //    .onMove(perform: moveItems)
    // }
    //
    // ... or this in the body:
    // NavigationLinkHidingChevron(selectedID: $selectedID, rowID: contact.id) {
    //    // Destination view such as Detail(for: item)
    // } label: {
    //    // Content for the list row
    // }
    // .contextMenu {
    //    ...
    // }
    // .overlay {
    //    HStack(spacing: 15) {
    //        // Right-justify the buttons
    //        Spacer()
    //        // Buttons that replace the chevron and take precedence over the row link
    //    }
    // }
    
    
    Login or Signup to reply.
  3. The Update solution from jnpdx almost worked for me, but it messed up the animation to the next view. Here’s what worked for me (is actually simpler than jnpdx’s answer):

    struct ContentView : View {
        @State private var linkActive = false
        
        var body: some View {
            NavigationView {
                List {
                    Button(action: { linkActive = true }) {
                        Image(systemName: "pencil")
                    }.overlay(
                        NavigationLink(
                            isActive: $linkActive,
                            destination: { Text("Test") },
                            label: { EmptyView() }
                        ).opacity(0)
                    )
                }
            }
        }
    }
    
    Login or Signup to reply.
  4. This worked for me, building on @wristbands’s solution and targeting iOS 16 using Xcode 14.1:

    struct ContentView : View {
        var body: some View {
            NavigationStack {
                List {
                    Text("View")    // your view here
                    .overlay {
                        NavigationLink(destination: { Text("Test") }, 
                                       label: { EmptyView() })
                            .opacity(0)
                    }
                }
            }
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search