Skip to content

Fix Keyboard events and KeyboardAvoidingView on Android (edge-to-edge)#55855

Open
zoontek wants to merge 5 commits intofacebook:mainfrom
zoontek:fix-keyboard-avoiding-view
Open

Fix Keyboard events and KeyboardAvoidingView on Android (edge-to-edge)#55855
zoontek wants to merge 5 commits intofacebook:mainfrom
zoontek:fix-keyboard-avoiding-view

Conversation

@zoontek
Copy link
Contributor

@zoontek zoontek commented Mar 2, 2026

Summary:

KeyboardAvoidingView has several issues on Android 15+ and when edgeToEdgeEnabled is set to true on older Android versions:

  1. Keyboard events relied on a legacy detection path for Android < 30 (checkForKeyboardEventsLegacy), which used height heuristics (heightDiff > mMinKeyboardHeightDetected) to guess whether the keyboard was visible. This approach is unreliable with edge-to-edge, where the visible display frame and screen dimensions differ from what the heuristic expects.

  2. keyboardDidHide reported incorrect screenY values. It used mVisibleViewArea.height(), which in edge-to-edge mode doesn't correspond to the actual screen bottom. This caused KeyboardAvoidingView to compute a non-zero keyboard overlap even after the keyboard was dismissed.

  3. KeyboardAvoidingView used _onKeyboardChange for keyboardDidHide on Android, which stores the event instead of nullifying it. After keyboard dismissal, any subsequent onLayout would re-enter _updateBottomIfNecessary with stale coordinates, causing a render loop (especially visible with behavior="height" in edge-to-edge mode, where frame.y shifts slightly on each layout cycle).

This PR:

  • Removes checkForKeyboardEventsLegacy and uses WindowInsetsCompat APIs (via AndroidX) for all Android versions, providing reliable keyboard detection in both legacy and edge-to-edge modes.
  • Fixes keyboardDidHide to report screenY as mVisibleViewArea.bottom + barInsets.bottom (the actual screen bottom including navigation bars).
  • Fixes the Android keyboardDidHide listener in KeyboardAvoidingView to use _onKeyboardHide (which nullifies _keyboardEvent), matching the iOS behavior and breaking the render loop.

Closes #49759

Changelog:

[ANDROID] [FIXED] - Fix KeyboardAvoidingView on Android 15+ / with edgeToEdgeEnabled

Test Plan:

Tested with rn-tester KeyboardAvoidingView example on:

  • Android 16 (API 36) (edge-to-edge is enforced)
  • Android 14 (API 34) with edgeToEdgeEnabled set to true or false
  • Android 7 (API 24) with edgeToEdgeEnabled set to true or false

For each, verified:

  • behavior="padding": keyboard open/close adjusts padding correctly
  • behavior="position": keyboard open/close translates content correctly
  • behavior="height": keyboard open/close works without render loop or glitching
  • keyboardDidShow and keyboardDidHide events report correct coordinates

@meta-cla meta-cla bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Mar 2, 2026
@facebook-github-bot facebook-github-bot added the Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team. label Mar 2, 2026
}
}

private void checkForKeyboardEventsLegacy() {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In order to simplify the codebase here, checkForKeyboardEventsLegacy is removed and checkForKeyboardEvents now uses AndroidX.

"keyboardDidHide",
createKeyboardEventPayload(
PixelUtil.toDIPFromPixel(mVisibleViewArea.height()),
PixelUtil.toDIPFromPixel(mVisibleViewArea.bottom + barInsets.bottom),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As mVisibleViewArea height doesn't include system UI height, we cannot rely on it when the app is edge-to-edge:

Image

} else {
this._subscriptions = [
Keyboard.addListener('keyboardDidHide', this._onKeyboardChange),
Keyboard.addListener('keyboardDidHide', this._onKeyboardHide),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This solves a crazy render loop (with the UI jumping back and forth) when using KeyboardAvoidingView with behavior="height"

@cipolleschi cipolleschi requested a review from cortinico March 3, 2026 14:02
@zoontek zoontek changed the title Fix keyboardDidHide event and KeyboardAvoidingView on Android (edge-to-edge) Fix Keyboard events and KeyboardAvoidingView on Android (edge-to-edge) Mar 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

KeyboardAvoidingView do not keep input in view under Android 15 (target SDK 35)

2 participants