Reject zeroed iOS keyboard frames in KeyboardCompatibleView - #3803
Closed
amit-hinge wants to merge 1 commit into
Closed
amit-hinge wants to merge 1 commit into
amit-hinge wants to merge 1 commit into
Conversation
β¦itionally The guard for keyboardFrame.screenY === 0 was gated behind AccessibilityInfo.prefersCrossFadeTransitions(), but iOS reports a zeroed frame in other cases too β notably when the device is locked while a text input is focused, which emits a burst of keyboardWillShow/keyboardDidShow events with all coordinates zeroed. Prefer Cross-Fade Transitions is a sub-setting of Reduce Motion and off for most users, so the guard rarely fired. When a zeroed frame reaches the height math, keyboardY becomes -keyboardVerticalOffset and relativeHeight resolves to the view's own bottom edge, which is then applied as paddingBottom. A screenY of 0 is never a real keyboard position, so reject it regardless of the accessibility setting. Dropping that accessibility call removes the only await in the chain, so _relativeKeyboardHeight, _updateBottomIfNecessary and _onLayout are now synchronous β required by the require-await lint rule, and it removes three microtask hops from the keyboard path.
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.
π― Goal
Companion to the repro in #3802 β this is the fix we applied on our side, opened as a draft in case it's useful to you. Not asking for a merge; happy for you to take it, adapt it, or close it.
_relativeKeyboardHeightguards against a zeroed keyboard frame only whenAccessibilityInfo.prefersCrossFadeTransitions()is true:But iOS reports a zeroed frame in at least one other situation: locking the device while a text input is focused emits a burst of
keyboardWillShow/keyboardDidShowevents with allendCoordinateszeroed (screenY: 0, height: 0, duration: 0). Prefer Cross-Fade Transitions is a sub-setting of Reduce Motion, so it's off for the vast majority of users and the guard effectively never fires for them.When a zeroed frame gets through,
keyboardYbecomes-keyboardVerticalOffsetandrelativeHeightresolves toframe.y + frame.heightβ the view's own bottom edge β which is then applied aspaddingBottom. Because the grown frame is re-measured by_onLayoutand feeds the next bogus event, it compounds.Worth noting for context:
KeyboardCompatibleViewitself is largely shielded today, because_handleAppStateChangecallsunsetKeyboardListeners()on background, so it isn't subscribed during the lock window. In our app the same flawed guard bit us via RN's ownKeyboardAvoidingView(which has noAppStatehandling) nested inside yours β that's what #3802 reproduces. So this change is defence-in-depth rather than a fix for a live bug in the SDK, which is why it's a draft.π Implementation details
Make the guard unconditional β a
screenYof 0 is never a real keyboard position:Dropping that accessibility call removes the only
awaitin the chain, so_relativeKeyboardHeight,_updateBottomIfNecessaryand_onLayoutbecome synchronous. That's required by therequire-awaitlint rule, and it also removes three microtask hops from the keyboard path. Happy to split that into its own commit if you'd prefer the guard change in isolation.π¨ UI Changes
None on the SDK's own surfaces. The only behavioral difference is on the zeroed-frame path, which previously produced a bogus padding value.
π§ͺ Testing
KeyboardCompatibleView, and nothing else inpackage/srcreferencesprefersCrossFadeTransitions, so there were no mocks to update.KeyboardAvoidingViewon a physical iOS device (viapatch-packagein our app): the guard fires on the zeroed frames, the composer no longer inflates, and the flicker is gone.unsetKeyboardListeners()means this path isn't reachable during the lock window forKeyboardCompatibleViewitself.Also worth flagging: this same gated guard is still present in React Native
main, so the underlying defect is upstream too.βοΈ Checklist
developbranchDraft β shared for your consideration alongside the repro in #3802.