fix: wrong offset for KeyboardAwareScrollView when keyboard resizes#1407
Closed
kirillzyusko wants to merge 7 commits intomainfrom
Closed
fix: wrong offset for KeyboardAwareScrollView when keyboard resizes#1407kirillzyusko wants to merge 7 commits intomainfrom
KeyboardAwareScrollView when keyboard resizes#1407kirillzyusko wants to merge 7 commits intomainfrom
Conversation
Contributor
📊 Package size report
|
KeyboardAwareScrollView when keyboard resizes
2 tasks
kirillzyusko
added a commit
that referenced
this pull request
Mar 31, 2026
… vs text) (#1417) ## 📜 Description Fixed a problem when switch text -> emoji -> text keeps pushing the content inside `KeyboardAwareScrollView` further and further. ## 💡 Motivation and Context The issue has been introduced in this PR: #760 The problem with: ```swift if UIResponder.current == currentResponder { return } ``` Is that when keyboard resizes we never emit `syncUpLayout` event. The fix proposed in this PR is safe, because: - we don't run full input listeners mount cycle; - we only emit additional event; - it's safe to emit this event multiple times (i. e. two times on focus) because we have this guard: ```swift if NSDictionary(dictionary: data).isEqual(to: lastEventDispatched) { return } ``` Another attempt to fix it has been added here #1407 But in #1407 we are trying to make JS code even more complex and the main problem is that with this fix documentation stays incorrect: > when keyboard changes its size (appears, disappears, changes size because of different input mode); So this is a better fix that fixes a native side of the platform. Closes #1318 #1407 ## 📢 Changelog <!-- High level overview of important changes --> <!-- For example: fixed status bar manipulation; added new types declarations; --> <!-- If your changes don't affect one of platform/language below - then remove this platform/language --> ### iOS - dispatch `syncUpLayout` if this event comes from keyboard notification; ## 🤔 How Has This Been Tested? Tested manually on iPhone 17 Pro (iOS 26.2) paper arch. ## 📸 Screenshots (if appropriate): |Before|After| |-------|-----| |<video src="https://github.com/user-attachments/assets/dab83232-e9c8-47f3-a128-5ebac517a9a4">|<video src="https://github.com/user-attachments/assets/50f74da1-a75f-458d-9f6f-e382fd688b0b">| ## 📝 Checklist - [x] CI successfully passed - [x] I added new mocks and corresponding unit-tests if library API was changed
Owner
Author
|
Closing in favour of #1417 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
📜 Description
Fixed an issue when resizing keyboard constantly pushes content up.
💡 Motivation and Context
When a user switches between keyboard types (e.g. text keyboard → emoji keyboard and back),
KeyboardAwareScrollViewwas accumulating scroll offset instead of converging to a stable position. Each toggle would push the scroll further, even though the input's actual on-screen position hadn't changed. It's caused by 2 bugs:1️⃣ Stale
absoluteYduring keyboard resizemaybeScrolluseslayout.value.absoluteYto determine how much to scroll. This value is populated by the nativeFocusedInputLayoutChangedevent. On iOS, the native observer usesKVOon the input's center relative to its superview (the scroll view's content area). When the scroll view scrolls, the input's center relative to the content doesn't change — only the scroll view's bounds.origin shifts — soKVOnever fires and absoluteY is never updated.As a result, when the emoji keyboard opens and the component scrolls (say)
+76px, the storedabsoluteYstill reflects the pre-scroll position. When switching back to the text keyboard,maybeScrollcomputes an overshoot based on that stale value, producing a cumulative drift on every toggle.On Android the native side does report updated
absoluteYon scroll, so only iOS is affected — but the stale-value case is latent everywhere.2️⃣
scrollBeforeKeyboardMovementwas clobbered on every keyboard resizeThis value is used as the interpolation base when the keyboard hides: we scroll back to it. It was being overwritten on every
onStartevent, including keyboard-size-only changes (emoji ↔ text). That meant after one toggle, the "home position" shifted, and hiding the keyboard would scroll to the wrong place.The fix consist from two parts.
For 1️⃣ problem - when
onStartfires for a keyboard-size change on the same input (keyboardWillChangeSize && !actualFocusChanged), we recompute absoluteY from first principles:layout.yis the input's Y offset relative to the scroll view's content — this is stable and never stale. Subtracting the current scroll offset and adding the scroll view's on-screen origin gives the true current position on screen, regardless of what the native side reported.For 2️⃣ problem - we gate the
scrollBeforeKeyboardMovementupdate behindactualFocusChanged. Keyboard-size-only changes (same target, different height) no longer disturb this value, so the scroll-back-on-hide always returns to the position captured at the original focus event.Closes #1318
📢 Changelog
JS
actualFocusChangedvariable insideonStarthandler;scrollBeforeKeyboardMovementonly ifactualFocusChanged===true(notfocusWasChanged);layout.value.absoluteYwhen keyboard gets resized;🤔 How Has This Been Tested?
Tested paper arch on:
📸 Screenshots (if appropriate):
Simulator.Screen.Recording.-.iPhone.17.Pro.-.2026-03-31.at.15.44.27.mov
Screen.Recording.2026-03-31.at.15.46.18.mov
📝 Checklist