diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/modal/ModalHostHelper.java b/ReactAndroid/src/main/java/com/facebook/react/views/modal/ModalHostHelper.java
new file mode 100644
index 00000000000000..94cff782361a07
--- /dev/null
+++ b/ReactAndroid/src/main/java/com/facebook/react/views/modal/ModalHostHelper.java
@@ -0,0 +1,45 @@
+// Copyright 2004-present Facebook. All Rights Reserved.
+
+package com.facebook.react.views.modal;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.graphics.Point;
+import android.view.Display;
+import android.view.Surface;
+import android.view.WindowManager;
+
+import com.facebook.infer.annotation.Assertions;
+
+/**
+ * Helper class for Modals.
+ */
+/*package*/ class ModalHostHelper {
+
+ private static final Point MIN_POINT = new Point();
+ private static final Point MAX_POINT = new Point();
+
+ /**
+ * To get the size of the screen, we use information from the WindowManager and
+ * default Display. We don't use DisplayMetricsHolder, or Display#getSize() because
+ * they return values that include the status bar. We only want the values of what
+ * will actually be shown on screen.
+ * This should only be called on the native modules/shadow nodes thread.
+ */
+ @TargetApi(16)
+ public static Point getModalHostSize(Context context) {
+ WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+ Display display = Assertions.assertNotNull(wm).getDefaultDisplay();
+ // getCurrentSizeRange will return the min and max width and height that the window can be
+ display.getCurrentSizeRange(MIN_POINT, MAX_POINT);
+
+ final int rotation = display.getRotation();
+ if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) {
+ // If we are vertical the width value comes from min width and height comes from max height
+ return new Point(MIN_POINT.x, MAX_POINT.y);
+ } else {
+ // If we are horizontal the width value comes from max width and height comes from min height
+ return new Point(MAX_POINT.x, MIN_POINT.y);
+ }
+ }
+}
diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/modal/ModalHostShadowNode.java b/ReactAndroid/src/main/java/com/facebook/react/views/modal/ModalHostShadowNode.java
new file mode 100644
index 00000000000000..f1e3b5adfb604d
--- /dev/null
+++ b/ReactAndroid/src/main/java/com/facebook/react/views/modal/ModalHostShadowNode.java
@@ -0,0 +1,38 @@
+/**
+ * Copyright (c) 2015-present, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+
+package com.facebook.react.views.modal;
+
+import android.graphics.Point;
+
+import com.facebook.csslayout.CSSNode;
+import com.facebook.react.uimanager.LayoutShadowNode;
+
+/**
+ * We implement the Modal by using an Android Dialog. That will fill the entire window of the
+ * application. To get layout to work properly, we need to layout all the elements within the
+ * Modal's inner content view as if they can fill the entire window. To do that, we need to
+ * explicitly set the styleWidth and styleHeight on the LayoutShadowNode of the child of this node
+ * to be the window size. This will then cause the children of the Modal to layout as if they can
+ * fill the window.
+ */
+class ModalHostShadowNode extends LayoutShadowNode {
+
+ /**
+ * We need to set the styleWidth and styleHeight of the one child (represented by the
+ * within the in Modal.js. This needs to fill the entire window.
+ */
+ @Override
+ public void addChildAt(CSSNode child, int i) {
+ super.addChildAt(child, i);
+ Point modalSize = ModalHostHelper.getModalHostSize(getThemedContext());
+ child.setStyleWidth(modalSize.x);
+ child.setStyleHeight(modalSize.y);
+ }
+}
diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostManager.java
index 3dad7b994aa13e..49b6d63e8abb61 100644
--- a/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostManager.java
+++ b/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostManager.java
@@ -17,6 +17,7 @@
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.common.MapBuilder;
+import com.facebook.react.uimanager.LayoutShadowNode;
import com.facebook.react.uimanager.PixelUtil;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.UIManagerModule;
@@ -47,6 +48,16 @@ protected ReactModalHostView createViewInstance(ThemedReactContext reactContext)
return new ReactModalHostView(reactContext);
}
+ @Override
+ public LayoutShadowNode createShadowNodeInstance() {
+ return new ModalHostShadowNode();
+ }
+
+ @Override
+ public Class extends LayoutShadowNode> getShadowNodeClass() {
+ return ModalHostShadowNode.class;
+ }
+
@Override
public void onDropViewInstance(ReactModalHostView view) {
super.onDropViewInstance(view);
diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostView.java b/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostView.java
index 6ac92391ea6053..ce8909bda42427 100644
--- a/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostView.java
+++ b/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostView.java
@@ -17,10 +17,8 @@
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Point;
-import android.view.Display;
import android.view.KeyEvent;
import android.view.MotionEvent;
-import android.view.Surface;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
@@ -267,8 +265,6 @@ private void updateProperties() {
static class DialogRootViewGroup extends ReactViewGroup implements RootView {
private final JSTouchDispatcher mJSTouchDispatcher = new JSTouchDispatcher(this);
- private final Point mMinPoint = new Point();
- private final Point mMaxPoint = new Point();
public DialogRootViewGroup(Context context) {
super(context);
@@ -282,33 +278,9 @@ protected void onSizeChanged(final int w, final int h, int oldw, int oldh) {
new Runnable() {
@Override
public void run() {
- // To get the size of the screen, we use information from the WindowManager and
- // default Display. We don't use DisplayMetricsHolder, or Display#getSize() because
- // they return values that include the status bar. We only want the values of what
- // will actually be shown on screen.
- Context context = getContext();
- WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
- Display display = Assertions.assertNotNull(wm.getDefaultDisplay());
- // getCurrentSizeRange will return the min and max width and height that the window
- // can be
- display.getCurrentSizeRange(mMinPoint, mMaxPoint);
-
- int width, height;
- int rotation = display.getRotation();
- if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) {
- // If we are vertical the width value comes from min width and height comes from
- // max height
- width = mMinPoint.x;
- height = mMaxPoint.y;
- } else {
- // If we are horizontal the width value comes from max width and height comes from
- // min height
- width = mMaxPoint.x;
- height = mMinPoint.y;
- }
-
+ Point modalSize = ModalHostHelper.getModalHostSize(getContext());
((ReactContext) getContext()).getNativeModule(UIManagerModule.class)
- .updateNodeSize(getChildAt(0).getId(), width, height);
+ .updateNodeSize(getChildAt(0).getId(), modalSize.x, modalSize.y);
}
});
}