Skip to content

Commit 32f5487

Browse files
NickGerlemanfacebook-github-bot
authored andcommitted
Do not use WindowInsetsCompat for Keyboard Events (#35897)
Summary: Pull Request resolved: #35897 Fixes #35894 Android 11 added native support for querying whether the IME is present along with its size, as part of the WindowInsets API. D38500859 (1e48274) changed our logic for Android keyboard events to use it when available, fixing a longstanding issues where we could not reliably tell where the keyboard was open depending on softInputMode. An androidx library WindowInsetsCompat aimed to backport some of the functionality to older versions of Android, with the same API, documenting IME queries to work down to API level 23 (Android 6). I used this, so that we would be able to remove our own logic for detecting keyboard insets once we supported 23+. From an issue report, WindowInsetsCompat is not accurately returning whether the IME is open on at least Android 9. So this change makes it so we only use WindowInsets methods when they are provided by the OS (a tested golden path), and otherwise use the previously working heuristics on anything older. Changelog: [Android][Fixed] - Do not use WindowInsetsCompat for Keyboard Events Reviewed By: christophpurrer Differential Revision: D42604176 fbshipit-source-id: da6a0bbc34c36f8e6d4e4ac07bc96da048fd6aa8
1 parent 26580a3 commit 32f5487

File tree

1 file changed

+38
-41
lines changed

1 file changed

+38
-41
lines changed

ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java

Lines changed: 38 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import android.app.Activity;
1616
import android.content.Context;
1717
import android.graphics.Canvas;
18+
import android.graphics.Insets;
1819
import android.graphics.Point;
1920
import android.graphics.Rect;
2021
import android.os.Build;
@@ -33,8 +34,6 @@
3334
import android.widget.FrameLayout;
3435
import androidx.annotation.Nullable;
3536
import androidx.annotation.RequiresApi;
36-
import androidx.core.graphics.Insets;
37-
import androidx.core.view.WindowInsetsCompat;
3837
import com.facebook.common.logging.FLog;
3938
import com.facebook.infer.annotation.Assertions;
4039
import com.facebook.infer.annotation.ThreadConfined;
@@ -776,7 +775,7 @@ public void runApplication() {
776775

777776
@VisibleForTesting
778777
/* package */ void simulateCheckForKeyboardForTesting() {
779-
if (Build.VERSION.SDK_INT >= 23) {
778+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
780779
getCustomGlobalLayoutListener().checkForKeyboardEvents();
781780
} else {
782781
getCustomGlobalLayoutListener().checkForKeyboardEventsLegacy();
@@ -907,9 +906,7 @@ public void onGlobalLayout() {
907906
return;
908907
}
909908

910-
// WindowInsetsCompat IME measurement is reliable for API level 23+.
911-
// https://developer.android.com/jetpack/androidx/releases/core#1.5.0-alpha02
912-
if (Build.VERSION.SDK_INT >= 23) {
909+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
913910
checkForKeyboardEvents();
914911
} else {
915912
checkForKeyboardEventsLegacy();
@@ -919,44 +916,44 @@ public void onGlobalLayout() {
919916
checkForDeviceDimensionsChanges();
920917
}
921918

922-
@RequiresApi(api = Build.VERSION_CODES.M)
919+
@RequiresApi(api = Build.VERSION_CODES.R)
923920
private void checkForKeyboardEvents() {
924921
getRootView().getWindowVisibleDisplayFrame(mVisibleViewArea);
925922
WindowInsets rootInsets = getRootView().getRootWindowInsets();
926-
if (rootInsets != null) {
927-
WindowInsetsCompat compatRootInsets = WindowInsetsCompat.toWindowInsetsCompat(rootInsets);
928-
929-
boolean keyboardIsVisible = compatRootInsets.isVisible(WindowInsetsCompat.Type.ime());
930-
if (keyboardIsVisible != mKeyboardIsVisible) {
931-
mKeyboardIsVisible = keyboardIsVisible;
932-
933-
if (keyboardIsVisible) {
934-
Insets imeInsets = compatRootInsets.getInsets(WindowInsetsCompat.Type.ime());
935-
Insets barInsets = compatRootInsets.getInsets(WindowInsetsCompat.Type.systemBars());
936-
int height = imeInsets.bottom - barInsets.bottom;
937-
938-
int softInputMode = ((Activity) getContext()).getWindow().getAttributes().softInputMode;
939-
int screenY =
940-
softInputMode == WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING
941-
? mVisibleViewArea.bottom - height
942-
: mVisibleViewArea.bottom;
943-
944-
sendEvent(
945-
"keyboardDidShow",
946-
createKeyboardEventPayload(
947-
PixelUtil.toDIPFromPixel(screenY),
948-
PixelUtil.toDIPFromPixel(mVisibleViewArea.left),
949-
PixelUtil.toDIPFromPixel(mVisibleViewArea.width()),
950-
PixelUtil.toDIPFromPixel(height)));
951-
} else {
952-
sendEvent(
953-
"keyboardDidHide",
954-
createKeyboardEventPayload(
955-
PixelUtil.toDIPFromPixel(mLastHeight),
956-
0,
957-
PixelUtil.toDIPFromPixel(mVisibleViewArea.width()),
958-
0));
959-
}
923+
if (rootInsets == null) {
924+
return;
925+
}
926+
927+
boolean keyboardIsVisible = rootInsets.isVisible(WindowInsets.Type.ime());
928+
if (keyboardIsVisible != mKeyboardIsVisible) {
929+
mKeyboardIsVisible = keyboardIsVisible;
930+
931+
if (keyboardIsVisible) {
932+
Insets imeInsets = rootInsets.getInsets(WindowInsets.Type.ime());
933+
Insets barInsets = rootInsets.getInsets(WindowInsets.Type.systemBars());
934+
int height = imeInsets.bottom - barInsets.bottom;
935+
936+
int softInputMode = ((Activity) getContext()).getWindow().getAttributes().softInputMode;
937+
int screenY =
938+
softInputMode == WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING
939+
? mVisibleViewArea.bottom - height
940+
: mVisibleViewArea.bottom;
941+
942+
sendEvent(
943+
"keyboardDidShow",
944+
createKeyboardEventPayload(
945+
PixelUtil.toDIPFromPixel(screenY),
946+
PixelUtil.toDIPFromPixel(mVisibleViewArea.left),
947+
PixelUtil.toDIPFromPixel(mVisibleViewArea.width()),
948+
PixelUtil.toDIPFromPixel(height)));
949+
} else {
950+
sendEvent(
951+
"keyboardDidHide",
952+
createKeyboardEventPayload(
953+
PixelUtil.toDIPFromPixel(mLastHeight),
954+
0,
955+
PixelUtil.toDIPFromPixel(mVisibleViewArea.width()),
956+
0));
960957
}
961958
}
962959
}

0 commit comments

Comments
 (0)