NavigationLink stops working if I add a .onLongPressGesture to my label element. Since .onTapGesture and .onLongPressGesture work well together, I thought these could coexist as well.
I've found answers that solved this for the old NavigationLink(titleKey:destination:isActive:) but none for the new NavigationLink(value:label:)
I'm also using different value types, so I'm unsure if I can use the NavigationStack(path:) and programmatically append values.
import SwiftUI
struct CombineLongPressAndNavigationLink: View {
@State private var rowColor: Color = .red
var body: some View {
NavigationStack {
ForEach(0..<50) { index in
NavigationLink(value: index) {
Rectangle().fill(rowColor)
.frame(height: 40)
.overlay {
Text("Navigate to \(index)")
}
// Uncomment and NavigationLink stops working
// .onLongPressGesture {
// rowColor = rowColor == .red ? .green : .red
// }
}
}
.navigationDestination(for: Int.self) { index in
Text("\(index)")
}
}
}
}
The same ideas in the solutions (using the deprecated NavigationLink
initialisers) here can be applied to value based navigation too.
The idea is that you handle both gestures (use .onTapGesture
and .onLongPressGesture
), and navigate programmatically.
Before, you needed a NavigationLink
with an isActive
parameter to programmatically navigate, but now you don't even need a NavigationLink
. You can just append a value to the navigation path.
Declare a navigation path as @State
.
@State private var path = [Int]()
// or if your path contains different types of values
@State private var path = NavigationPath()
Pass it to NavigationStack(path: $path)
, and use the Rectangle().fill(rowColor)
directly.
NavigationStack(path: $path) {
ForEach(0..<50) { index in
Rectangle().fill(rowColor)
.frame(height: 40)
.overlay {
Text("Navigate to \(index)")
}
.onTapGesture {
// here we programmatically navigate
path.append(index)
}
.onLongPressGesture {
rowColor = rowColor == .red ? .green : .red
}
}
.navigationDestination(for: Int.self) { index in
Text("\(index)")
}
}