12
12
import static com .facebook .react .uimanager .common .UIManagerType .FABRIC ;
13
13
import static com .facebook .systrace .Systrace .TRACE_TAG_REACT_JAVA_BRIDGE ;
14
14
15
+ import android .app .Activity ;
15
16
import android .content .Context ;
16
17
import android .graphics .Canvas ;
17
18
import android .graphics .Point ;
31
32
import android .view .WindowManager ;
32
33
import android .widget .FrameLayout ;
33
34
import androidx .annotation .Nullable ;
35
+ import androidx .annotation .RequiresApi ;
36
+ import androidx .core .graphics .Insets ;
37
+ import androidx .core .view .WindowInsetsCompat ;
34
38
import com .facebook .common .logging .FLog ;
35
39
import com .facebook .infer .annotation .Assertions ;
36
40
import com .facebook .infer .annotation .ThreadConfined ;
@@ -770,7 +774,11 @@ public void runApplication() {
770
774
771
775
@ VisibleForTesting
772
776
/* package */ void simulateCheckForKeyboardForTesting () {
773
- getCustomGlobalLayoutListener ().checkForKeyboardEvents ();
777
+ if (Build .VERSION .SDK_INT >= 23 ) {
778
+ getCustomGlobalLayoutListener ().checkForKeyboardEvents ();
779
+ } else {
780
+ getCustomGlobalLayoutListener ().checkForKeyboardEventsLegacy ();
781
+ }
774
782
}
775
783
776
784
private CustomGlobalLayoutListener getCustomGlobalLayoutListener () {
@@ -879,7 +887,8 @@ private class CustomGlobalLayoutListener implements ViewTreeObserver.OnGlobalLay
879
887
private final Rect mVisibleViewArea ;
880
888
private final int mMinKeyboardHeightDetected ;
881
889
882
- private int mKeyboardHeight = 0 ;
890
+ private boolean mKeyboardIsVisible = false ;
891
+ private int mKeyboardHeight = 0 ; // Only used in checkForKeyboardEventsLegacy path
883
892
private int mDeviceRotation = 0 ;
884
893
885
894
/* package */ CustomGlobalLayoutListener () {
@@ -895,13 +904,62 @@ public void onGlobalLayout() {
895
904
|| mReactInstanceManager .getCurrentReactContext () == null ) {
896
905
return ;
897
906
}
898
- checkForKeyboardEvents ();
907
+
908
+ // WindowInsetsCompat IME measurement is reliable for API level 23+.
909
+ // https://developer.android.com/jetpack/androidx/releases/core#1.5.0-alpha02
910
+ if (Build .VERSION .SDK_INT >= 23 ) {
911
+ checkForKeyboardEvents ();
912
+ } else {
913
+ checkForKeyboardEventsLegacy ();
914
+ }
915
+
899
916
checkForDeviceOrientationChanges ();
900
917
checkForDeviceDimensionsChanges ();
901
918
}
902
919
920
+ @ RequiresApi (api = Build .VERSION_CODES .M )
903
921
private void checkForKeyboardEvents () {
904
922
getRootView ().getWindowVisibleDisplayFrame (mVisibleViewArea );
923
+ WindowInsets rootInsets = getRootView ().getRootWindowInsets ();
924
+ WindowInsetsCompat compatRootInsets = WindowInsetsCompat .toWindowInsetsCompat (rootInsets );
925
+
926
+ boolean keyboardIsVisible = compatRootInsets .isVisible (WindowInsetsCompat .Type .ime ());
927
+ if (keyboardIsVisible != mKeyboardIsVisible ) {
928
+ mKeyboardIsVisible = keyboardIsVisible ;
929
+
930
+ if (keyboardIsVisible ) {
931
+ Insets imeInsets = compatRootInsets .getInsets (WindowInsetsCompat .Type .ime ());
932
+ Insets barInsets = compatRootInsets .getInsets (WindowInsetsCompat .Type .systemBars ());
933
+ int height = imeInsets .bottom - barInsets .bottom ;
934
+
935
+ int softInputMode = ((Activity ) getContext ()).getWindow ().getAttributes ().softInputMode ;
936
+ int screenY =
937
+ softInputMode == WindowManager .LayoutParams .SOFT_INPUT_ADJUST_NOTHING
938
+ ? mVisibleViewArea .bottom - height
939
+ : mVisibleViewArea .bottom ;
940
+
941
+ sendEvent (
942
+ "keyboardDidShow" ,
943
+ createKeyboardEventPayload (
944
+ PixelUtil .toDIPFromPixel (screenY ),
945
+ PixelUtil .toDIPFromPixel (mVisibleViewArea .left ),
946
+ PixelUtil .toDIPFromPixel (mVisibleViewArea .width ()),
947
+ PixelUtil .toDIPFromPixel (height )));
948
+ } else {
949
+ sendEvent (
950
+ "keyboardDidHide" ,
951
+ createKeyboardEventPayload (
952
+ PixelUtil .toDIPFromPixel (mLastHeight ),
953
+ 0 ,
954
+ PixelUtil .toDIPFromPixel (mVisibleViewArea .width ()),
955
+ 0 ));
956
+ }
957
+ }
958
+ }
959
+
960
+ private void checkForKeyboardEventsLegacy () {
961
+ getRootView ().getWindowVisibleDisplayFrame (mVisibleViewArea );
962
+
905
963
int notchHeight = 0 ;
906
964
if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .P ) {
907
965
WindowInsets insets = getRootView ().getRootWindowInsets ();
@@ -919,8 +977,10 @@ private void checkForKeyboardEvents() {
919
977
920
978
boolean isKeyboardShowingOrKeyboardHeightChanged =
921
979
mKeyboardHeight != heightDiff && heightDiff > mMinKeyboardHeightDetected ;
980
+
922
981
if (isKeyboardShowingOrKeyboardHeightChanged ) {
923
982
mKeyboardHeight = heightDiff ;
983
+ mKeyboardIsVisible = true ;
924
984
sendEvent (
925
985
"keyboardDidShow" ,
926
986
createKeyboardEventPayload (
@@ -934,6 +994,7 @@ private void checkForKeyboardEvents() {
934
994
boolean isKeyboardHidden = mKeyboardHeight != 0 && heightDiff <= mMinKeyboardHeightDetected ;
935
995
if (isKeyboardHidden ) {
936
996
mKeyboardHeight = 0 ;
997
+ mKeyboardIsVisible = false ;
937
998
sendEvent (
938
999
"keyboardDidHide" ,
939
1000
createKeyboardEventPayload (
0 commit comments