Skip to content

Commit 91d34e1

Browse files
alanleedevfacebook-github-bot
authored andcommitted
Re-emit keyboardDidShow on IME height change
Summary: Follow-up to D100437445, which replaced the legacy height-based IME detector in `ReactRootView.CustomGlobalLayoutListener` with a visibility-only detector (`WindowInsetsCompat.Type.ime()`). The legacy code also re-emitted `keyboardDidShow` whenever the IME *height* changed while still visible (e.g., user toggles the emoji panel or predictive bar). Removing that left these JS consumers reading stale `endCoordinates`: - `KeyboardAvoidingView` — caches `_keyboardEvent`, no longer resizes on IME height changes. - `ScrollView` — caches `_keyboardMetrics`; focused `TextInput` auto-scroll uses stale `screenY`/`height`. - `Keyboard.metrics()` — public API returning the cached payload from the last `keyboardDidShow`. Fix: track the last reported IME height and re-emit `keyboardDidShow` when the keyboard is visible AND (it just appeared OR the height changed), restoring pre-D100437445 semantics. The hide branch is gated on `mKeyboardIsVisible` so it still fires exactly once per cycle. Changelog: [Android][Fixed] KeyboardAvoidingView and TextInput auto-scroll not responding to IME height changes (e.g., when toggling emoji panel or predictive bar) Differential Revision: D101385688
1 parent 6530092 commit 91d34e1

1 file changed

Lines changed: 22 additions & 14 deletions

File tree

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -931,6 +931,7 @@ private class CustomGlobalLayoutListener implements ViewTreeObserver.OnGlobalLay
931931
private final Rect mVisibleViewArea;
932932

933933
private boolean mKeyboardIsVisible = false;
934+
private int mKeyboardHeight = 0;
934935
private int mDeviceRotation = 0;
935936

936937
/* package */ CustomGlobalLayoutListener() {
@@ -957,13 +958,17 @@ private void checkForKeyboardEvents() {
957958
}
958959

959960
boolean keyboardIsVisible = rootInsets.isVisible(WindowInsetsCompat.Type.ime());
960-
if (keyboardIsVisible != mKeyboardIsVisible) {
961-
mKeyboardIsVisible = keyboardIsVisible;
962-
Insets barInsets = rootInsets.getInsets(WindowInsetsCompat.Type.systemBars());
961+
Insets barInsets = rootInsets.getInsets(WindowInsetsCompat.Type.systemBars());
963962

964-
if (keyboardIsVisible) {
965-
Insets imeInsets = rootInsets.getInsets(WindowInsetsCompat.Type.ime());
966-
int height = imeInsets.bottom - barInsets.bottom;
963+
if (keyboardIsVisible) {
964+
Insets imeInsets = rootInsets.getInsets(WindowInsetsCompat.Type.ime());
965+
int height = imeInsets.bottom - barInsets.bottom;
966+
967+
// Re-emit on height change while keyboard stays visible (e.g., emoji
968+
// panel toggle); JS consumers cache endCoordinates from keyboardDidShow.
969+
if (!mKeyboardIsVisible || height != mKeyboardHeight) {
970+
mKeyboardIsVisible = true;
971+
mKeyboardHeight = height;
967972

968973
ViewGroup.LayoutParams rootLayoutParams = getRootView().getLayoutParams();
969974
Assertions.assertCondition(rootLayoutParams instanceof WindowManager.LayoutParams);
@@ -981,15 +986,18 @@ private void checkForKeyboardEvents() {
981986
PixelUtil.toDIPFromPixel(mVisibleViewArea.left),
982987
PixelUtil.toDIPFromPixel(mVisibleViewArea.width()),
983988
PixelUtil.toDIPFromPixel(height)));
984-
} else {
985-
sendEvent(
986-
"keyboardDidHide",
987-
createKeyboardEventPayload(
988-
PixelUtil.toDIPFromPixel(mVisibleViewArea.bottom + barInsets.bottom),
989-
0,
990-
PixelUtil.toDIPFromPixel(mVisibleViewArea.width()),
991-
0));
992989
}
990+
} else if (mKeyboardIsVisible) {
991+
mKeyboardIsVisible = false;
992+
mKeyboardHeight = 0;
993+
994+
sendEvent(
995+
"keyboardDidHide",
996+
createKeyboardEventPayload(
997+
PixelUtil.toDIPFromPixel(mVisibleViewArea.bottom + barInsets.bottom),
998+
0,
999+
PixelUtil.toDIPFromPixel(mVisibleViewArea.width()),
1000+
0));
9931001
}
9941002
}
9951003

0 commit comments

Comments
 (0)