Follow-up to #1591 / #1598, as requested — filing separately rather than reopening.
#1598 resets prevKeyboardPosition = 0 at keyboardDidHide, on the premise that a completed hide means the keyboard is at zero. On iOS 26 that premise doesn't hold when a TextInput's inputView is swapped for a custom panel: didHide arrives while the keyboard is still descending.
I have a patched build that logs the tracking view's own presentation measurement (frameTransitionInWindow, the same read updateKeyboardFrame trusts) at each will-event. From one capture on device:
032285 willHide
032288 tick: h=335 y=539 prev=335 keyboard still fully up
032327 didHide 42ms later
032330 measured=249 prev=335 keyboard is at 249, not 0
032330 willShow
032345 tick: h=211 still descending after willShow
Same capture, second occurrence: willHide → didHide 60ms later, keyboard measured at 193. A separate capture (navigation transition with a retained responder) shows the mirror case — measured=335 prev=34, i.e. prev stale low while the keyboard stands fully up.
So there are three values in play at a will-event: the stale prev, the constant 0, and the measurement. Only the third matched the keyboard in these captures. What worked for me was re-seeding prevKeyboardPosition from the measured presentation at each will-event (skipping the seed when the read is degenerate — no window, or keyboardFrameY == 0) rather than resetting at didHide. Happy to be wrong about the right shape of the fix — the reported observation is just that didHide is not a reliable "height is 0" signal.
Environment: iOS 26, iPhone, RN 0.86.2 (Expo SDK 57), new arch, Hermes, RNKC 1.21.9 with local diagnostics compiled in.
Repro: none yet — these came off a production app. The reducible shape is a TextInput whose inputView is swapped between the system keyboard and a custom panel, toggled rapidly.
Follow-up to #1591 / #1598, as requested — filing separately rather than reopening.
#1598 resets prevKeyboardPosition = 0 at keyboardDidHide, on the premise that a completed hide means the keyboard is at zero. On iOS 26 that premise doesn't hold when a TextInput's inputView is swapped for a custom panel: didHide arrives while the keyboard is still descending.
I have a patched build that logs the tracking view's own presentation measurement (frameTransitionInWindow, the same read updateKeyboardFrame trusts) at each will-event. From one capture on device:
032285 willHide
032288 tick: h=335 y=539 prev=335 keyboard still fully up
032327 didHide 42ms later
032330 measured=249 prev=335 keyboard is at 249, not 0
032330 willShow
032345 tick: h=211 still descending after willShow
Same capture, second occurrence: willHide → didHide 60ms later, keyboard measured at 193. A separate capture (navigation transition with a retained responder) shows the mirror case — measured=335 prev=34, i.e. prev stale low while the keyboard stands fully up.
So there are three values in play at a will-event: the stale prev, the constant 0, and the measurement. Only the third matched the keyboard in these captures. What worked for me was re-seeding prevKeyboardPosition from the measured presentation at each will-event (skipping the seed when the read is degenerate — no window, or keyboardFrameY == 0) rather than resetting at didHide. Happy to be wrong about the right shape of the fix — the reported observation is just that didHide is not a reliable "height is 0" signal.
Environment: iOS 26, iPhone, RN 0.86.2 (Expo SDK 57), new arch, Hermes, RNKC 1.21.9 with local diagnostics compiled in.
Repro: none yet — these came off a production app. The reducible shape is a TextInput whose inputView is swapped between the system keyboard and a custom panel, toggled rapidly.