NavigationLink as a Button in a list

83 Views Asked by At

I have NavigationStack with a List. I would like a NavigationLink to only trigger when Image(systemName: "info.circle") is tapped. Anywhere I place the NavigationLink, the whole row acts as a link button to new view.

NavigationStack(path: $navigationPath) {
        List {
            ForEach(aircraftVM.aircraftCollect, id: \.id) { aircraft in
                    HStack{
                        VStack(alignment: .leading) {
                            Text(aircraft.registration ?? "")
                            Text(aircraft.type ?? "")
                                .font(.callout)
                                .foregroundStyle(.secondary)
                            Text(aircraft.aircraftRemarks ?? "")
                                .font(.footnote)
                                .foregroundStyle(.secondary)
                        }
                    
                        NavigationLink(value: aircraft) {
                            Image(systemName: "info.circle")
                        }
                    }
                
            }
            .onDelete(perform: delete)
        }
        
        .navigationDestination(for: AircraftEntity.self) { aircraft in
            AircraftDatabaseDetailView(aircraft: aircraft)
        }
2

There are 2 best solutions below

0
On BEST ANSWER

I was curious and built out a working copy of your code. The key items are .buttonStyle(.borderless) and using a Button(action:,label:)

import SwiftUI

struct Aircraft : Hashable{
  var id = UUID()
  var type : String = "Boeing 747"
  var details : String = "In Service"
}

struct ContentView: View {
  
  @State var aircraftArray = [Aircraft]()
  @State var navigationPath = [Aircraft]()
  
  var body: some View {
    NavigationStack(path: $navigationPath) {
      if aircraftArray.count > 0 {
        List {
          ForEach(0..<10) { index in
            HStack{
              VStack(alignment: .leading) {
                Text(aircraftArray[index].id.uuidString.prefix(4))
                Text(aircraftArray[index].type)
                  .font(.callout)
                  .foregroundStyle(.secondary)
                Text(aircraftArray[index].details)
                  .font(.footnote)
                  .foregroundStyle(.secondary)
              }
              
              Button {
                navigationPath.append(aircraftArray[index])
              } label: {
                Image(systemName: "info.circle")
              }
            }
          }
        }
        .buttonStyle(.borderless)
        .navigationDestination(for: Aircraft.self) { aircraft in
            AircraftDatabaseDetailView(aircraft: aircraft)
        }
      }
    }
    .onAppear {
      // Populate the aircraft array
      for _ in 0...10 {
        aircraftArray.append(Aircraft())
      }
    }
  }
  
  private func delete() {}
}

struct AircraftDatabaseDetailView: View {
  var aircraft : Aircraft
  var body: some View {
    VStack {
      Text(aircraft.id.uuidString.prefix(4))
      Text(aircraft.type)
      Text(aircraft.details)
    }
    .navigationBarTitleDisplayMode(.inline)
  }
}
3
On

Try this solution, replace your NavigationLink with Button, then set buttonStyle for List to .borderless:

NavigationStack(path: $navigationPath) {
    List {
        ForEach(aircraftVM.aircraftCollect, id: \.id) { aircraft in
            HStack {
                VStack(alignment: .leading) {
                    Text("Hello")
                    Text(aircraft.registration ?? "")
                    Text(aircraft.type ?? "")
                        .font(.callout)
                        .foregroundStyle(.secondary)
                    Text(aircraft.aircraftRemarks ?? "")
                        .font(.footnote)
                        .foregroundStyle(.secondary)
                }
                
                Button {
                    navigationPath.append(aircraft)
                } label: {
                    Image(systemName: "info.circle")
                }
                .navigationDestination(for: AircraftEntity.self) { aircraft in
                    AircraftDatabaseDetailView(aircraft: aircraft)
                }
            }
        }
        .onDelete(perform: delete)
    }
    .buttonStyle(.borderless)
}