Improve POI context menu open speed & smoothness #5460
Conversation
| [UIView animateWithDuration:0.3 animations:^{ | ||
|
|
||
| [self.customController setRowUpdatesDeferred:YES]; | ||
| [UIView animateWithDuration:0.15 animations:^{ |
There was a problem hiding this comment.
In Android, mainView.animate().y(posY).setDuration(200) is used. I'd use the same duration here(0.2). We should also align the animation timing with the designer
| _grPointContextMenu.delegate = self; | ||
|
|
||
| // prevents single tap to fire together with double tap | ||
| [_grSymbolContextMenu requireGestureRecognizerToFail:_grZoomIn]; |
There was a problem hiding this comment.
This change introduces a regression compared to the previous requireGestureRecognizerToFail: behavior.
The current implementation relies on a fixed 0.15s delay before opening the context menu. However, a valid double tap can still occur after that delay (while remaining within iOS double-tap recognition timing). In that case, the delayed block may already have executed and opened the POI menu before zoomInGestureDetected is triggered.
zoomInGestureDetected only cancels the pending block, but it does not dismiss a menu that has already been shown. As a result, a double-tap-to-zoom gesture can also display the context menu.
The previous requireGestureRecognizerToFail: approach did not have this issue because it waited for the system double-tap recognition window before handling the single-tap action.
Could we preserve the previous behavior or otherwise ensure that the context menu is not shown when a valid double tap is recognized?
There was a problem hiding this comment.
The 0.15s delay is shorter than the system's double-tap window, so a valid second tap can arrive after the block already opened the POI menu. By then cancelPendingContextMenu has nothing to cancel, and the menu stays up on a double-tap zoom.
Increasing the delay won't help: iOS doesn't expose the real double-tap interval, and any safe value would bring back the latency this task removed.
So I handle both cases instead. zoomInGestureDetected: now also dismisses the menu if the delayed block already showed it (within a short 0.4s guard tied to the double-tap, so an unrelated menu is never closed). If the block hasn't fired yet, it's just cancelled as before.
Reduces the perceived latency and jank when opening the POI context menu on tap, bringing it closer to the Android timing.
Changes
Single-tap delay instead of requireGestureRecognizerToFail. Removed the requireGestureRecognizerToFail: links between the single-tap context-menu recognizer and the zoom recognizers (they imposed the system's ~400 ms double-tap arbitration on every tap). Replaced with a tunable kSingleTapContextMenuDelay (0.15 s): the menu is scheduled after the tap and cancelled if a second tap begins (touch.tapCount >= 2) or a double-tap zoom fires. Net effect: single tap opens faster while double-tap-to-zoom still works.
Two-phase menu build. On a collapsed open (showFullMenu == NO) only the header rows are built before the slide; the detail rows are built right after the slide completes (setDetailRowsDeferred: / buildDeferredDetailRows). This keeps the table render off the animation's critical path.
Deferred row reloads during the slide (setRowUpdatesDeferred:) so async row updates don't reload the table mid-animation.
Marker and selection polygon drawn first. Menu presentation now yields one runloop cycle before building the menu controller, so the context pin marker and the selected-object polygon/contour highlight render immediately, before the heavier controller/menu build runs.
Slide animation 0.3 s → 0.15 s.