Skip to content
18 changes: 17 additions & 1 deletion ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@
import android.graphics.Canvas;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Build;
import android.os.Bundle;
import android.util.AttributeSet;
import android.view.DisplayCutout;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.Surface;
Expand Down Expand Up @@ -647,6 +649,11 @@ public void runApplication() {
mJSTouchDispatcher = new JSTouchDispatcher(this);
}

@VisibleForTesting
/* package */ void simulateCheckForKeyboardForTesting() {
getCustomGlobalLayoutListener().checkForKeyboardEvents();
}

private CustomGlobalLayoutListener getCustomGlobalLayoutListener() {
if (mCustomGlobalLayoutListener == null) {
mCustomGlobalLayoutListener = new CustomGlobalLayoutListener();
Expand Down Expand Up @@ -766,8 +773,17 @@ public void onGlobalLayout() {

private void checkForKeyboardEvents() {
getRootView().getWindowVisibleDisplayFrame(mVisibleViewArea);
int notchHeight = 0;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
DisplayCutout displayCutout = getRootView().getRootWindowInsets().getDisplayCutout();
if (displayCutout != null) {
notchHeight = displayCutout.getSafeInsetTop();
}
}
final int heightDiff =
DisplayMetricsHolder.getWindowDisplayMetrics().heightPixels - mVisibleViewArea.bottom;
DisplayMetricsHolder.getWindowDisplayMetrics().heightPixels
- mVisibleViewArea.bottom
+ notchHeight;

boolean isKeyboardShowingOrKeyboardHeightChanged =
mKeyboardHeight != heightDiff && heightDiff > mMinKeyboardHeightDetected;
Expand Down
43 changes: 43 additions & 0 deletions ReactAndroid/src/test/java/com/facebook/react/RootViewTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;

import android.graphics.Rect;
import android.view.MotionEvent;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.CatalystInstance;
Expand All @@ -25,7 +26,9 @@
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactTestHelper;
import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.common.SystemClock;
import com.facebook.react.modules.core.DeviceEventManagerModule.RCTDeviceEventEmitter;
import com.facebook.react.uimanager.DisplayMetricsHolder;
import com.facebook.react.uimanager.UIManagerModule;
import com.facebook.react.uimanager.events.Event;
Expand All @@ -37,6 +40,7 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.powermock.api.mockito.PowerMockito;
Expand Down Expand Up @@ -209,4 +213,43 @@ public void testRemountApplication() {
rootView.unmountReactApplication();
rootView.startReactApplication(instanceManager, "");
}

@Test
public void testCheckForKeyboardEvents() {
ReactInstanceManager instanceManager = mock(ReactInstanceManager.class);
RCTDeviceEventEmitter eventEmitterModuleMock = mock(RCTDeviceEventEmitter.class);

when(instanceManager.getCurrentReactContext()).thenReturn(mReactContext);
when(mReactContext.getJSModule(RCTDeviceEventEmitter.class)).thenReturn(eventEmitterModuleMock);

ReactRootView rootView =
new ReactRootView(mReactContext) {
@Override
public void getWindowVisibleDisplayFrame(Rect outRect) {
if (outRect.bottom == 0) {
outRect.bottom += 100;
outRect.right += 370;
} else {
outRect.bottom += 370;
}
}
};

rootView.startReactApplication(instanceManager, "");
rootView.simulateCheckForKeyboardForTesting();

WritableMap params = Arguments.createMap();
WritableMap endCoordinates = Arguments.createMap();
double screenHeight = 470.0;
double keyboardHeight = 100.0;
params.putDouble("duration", 0.0);
endCoordinates.putDouble("width", screenHeight - keyboardHeight);
endCoordinates.putDouble("screenX", 0.0);
endCoordinates.putDouble("height", screenHeight - keyboardHeight);
endCoordinates.putDouble("screenY", keyboardHeight);
params.putMap("endCoordinates", endCoordinates);
params.putString("easing", "keyboard");

verify(eventEmitterModuleMock, Mockito.times(1)).emit("keyboardDidShow", params);
}
}