-
Notifications
You must be signed in to change notification settings - Fork 172
Description
Description
When viewing the key details screen with a scrollable list of derived keys, tapping on a key row does not trigger any action until the user scrolls the list at least once. After scrolling, tap gestures work correctly.
Steps to Reproduce
- Open the app and navigate to a key-set that has multiple derived keys
- Ensure the list of derived keys is scrollable (more keys than fit on screen)
- Without scrolling, tap on any visible derived key row
- Observe: Nothing happens - the tap gesture is not recognized
- Scroll the list slightly (even just a tiny bit)
- Tap on any derived key row again
- Observe: Tap gesture now works correctly and navigates to key details
Expected Behavior
Tap gestures on derived key rows should work immediately when the screen loads, without requiring any scrolling interaction first.
Actual Behavior
Tap gestures are not recognized until after the user performs at least one scroll gesture on the list.
Root Cause
The issue is caused by a combination of factors:
- NavigationLink placement: The
NavigationLinkwas placed inside theLazyVStack, which can interfere with gesture recognition in SwiftUI - LazyVStack gesture initialization:
LazyVStackinside aScrollViewcan have delayed gesture recognizer initialization, especially for items that are initially visible without scrolling - Tap area coverage: The tap gesture area may not cover the full width of the row initially
Solution
The fix involves two key changes to ios/PolkadotVault/Screens/KeyDetails/Views/KeyDetailsView+MainList.swift:
-
Move NavigationLink to ZStack overlay: Changed the container from
VStacktoZStackand placed theNavigationLinkas an overlay, isolating it from the scrollable content. This matches the pattern used inLogsListView.swift. -
Ensure full-width tap area: Added
.frame(maxWidth: .infinity)to each derived key row to ensure the entire width is tappable from the start.
Code Changes
// NavigationLink inside LazyVStack
LazyVStack(spacing: 0) {
ForEach(...) { deriveKey in
DerivedKeyRow(...)
.contentShape(Rectangle())
.onTapGesture { ... }
}
NavigationLink(...) { EmptyView() } // ❌ Inside LazyVStack
}
// Proposed solution - NavigationLink in ZStack overlay
ZStack {
ScrollView(...) {
LazyVStack(spacing: 0) {
ForEach(...) { deriveKey in
DerivedKeyRow(...)
.frame(maxWidth: .infinity) // ✅ Full width tap area
.contentShape(Rectangle())
.onTapGesture { ... }
}
}
}
NavigationLink(...) { EmptyView() } // ✅ In overlay layer
}Environment
- Platform: iOS
- Component: Key Details Screen (
KeyDetailsView) - File:
ios/PolkadotVault/Screens/KeyDetails/Views/KeyDetailsView+MainList.swift
Additional Context
This is a SwiftUI-specific issue related to gesture recognizer initialization in lazy-loaded views. The pattern of using ZStack with NavigationLink as an overlay is a common solution for this type of gesture conflict in SwiftUI applications.