From f8d623ca3a4c8ccbfa34fbe3d0a03c3935619dd3 Mon Sep 17 00:00:00 2001 From: Ahmed El-Helw Date: Wed, 29 Jun 2016 15:31:28 -0700 Subject: [PATCH] Fix modals when using Nodes Summary: Modals were broken in Nodes, because the custom measurement logic for all the children of the ReactModalShadowNode was not being applied (because we wrapped it in a NativeViewWrapper). This change adds a custom flat node type for modals. Differential Revision: D3499557 --- .../react/flat/FlatReactModalShadowNode.java | 94 +++++++++++++++++++ .../react/flat/FlatUIImplementation.java | 1 + .../react/flat/RCTModalHostManager.java | 31 ++++++ 3 files changed, 126 insertions(+) create mode 100644 ReactAndroid/src/main/java/com/facebook/react/flat/FlatReactModalShadowNode.java create mode 100644 ReactAndroid/src/main/java/com/facebook/react/flat/RCTModalHostManager.java diff --git a/ReactAndroid/src/main/java/com/facebook/react/flat/FlatReactModalShadowNode.java b/ReactAndroid/src/main/java/com/facebook/react/flat/FlatReactModalShadowNode.java new file mode 100644 index 0000000000..8f754287f2 --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/flat/FlatReactModalShadowNode.java @@ -0,0 +1,94 @@ +/** + * 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.flat; + +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.csslayout.CSSNode; + +/** + * FlatReactModalShadowNode + * + * This is a Nodes specific shadow node for modals. This is required because we wrap any + * non-FlatShadowNode node in a NativeViewWrapper. In the case of a modal shadow node, we need + * to treat it as its own node so that we can add the custom measurement behavior that is there + * in the non-Nodes version when we add a child. + * + * {@see {@link com.facebook.react.views.modal.ModalHostShadowNode}} + */ +class FlatReactModalShadowNode extends FlatShadowNode implements AndroidView { + + private final Point mMinPoint = new Point(); + private final Point mMaxPoint = new Point(); + private boolean mPaddingChanged; + + FlatReactModalShadowNode() { + forceMountToView(); + forceMountChildrenToView(); + } + + /** + * 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 + @TargetApi(16) + public void addChildAt(CSSNode child, int i) { + super.addChildAt(child, i); + + Context context = getThemedContext(); + WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + Display display = 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; + } + child.setStyleWidth(width); + child.setStyleHeight(height); + } + + @Override + public boolean needsCustomLayoutForChildren() { + return false; + } + + @Override + public boolean isPaddingChanged() { + return mPaddingChanged; + } + + @Override + public void resetPaddingChanged() { + mPaddingChanged = false; + } + + @Override + public void setPadding(int spacingType, float padding) { + if (getPadding().set(spacingType, padding)) { + mPaddingChanged = true; + dirty(); + } + } +} diff --git a/ReactAndroid/src/main/java/com/facebook/react/flat/FlatUIImplementation.java b/ReactAndroid/src/main/java/com/facebook/react/flat/FlatUIImplementation.java index a38dbdac8f..7b7fb54f2e 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/flat/FlatUIImplementation.java +++ b/ReactAndroid/src/main/java/com/facebook/react/flat/FlatUIImplementation.java @@ -57,6 +57,7 @@ public class FlatUIImplementation extends UIImplementation { viewManagers.add(new RCTTextInlineImageManager()); viewManagers.add(new RCTImageViewManager()); viewManagers.add(new RCTTextInputManager()); + viewManagers.add(new RCTModalHostManager(reactContext)); ViewManagerRegistry viewManagerRegistry = new ViewManagerRegistry(viewManagers); FlatNativeViewHierarchyManager nativeViewHierarchyManager = new FlatNativeViewHierarchyManager( diff --git a/ReactAndroid/src/main/java/com/facebook/react/flat/RCTModalHostManager.java b/ReactAndroid/src/main/java/com/facebook/react/flat/RCTModalHostManager.java new file mode 100644 index 0000000000..d7420bc984 --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/flat/RCTModalHostManager.java @@ -0,0 +1,31 @@ +/** + * 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.flat; + +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.uimanager.LayoutShadowNode; +import com.facebook.react.views.modal.ReactModalHostManager; + +/* package */ class RCTModalHostManager extends ReactModalHostManager { + + /* package */ RCTModalHostManager(ReactApplicationContext context) { + super(context); + } + + @Override + public LayoutShadowNode createShadowNodeInstance() { + return new FlatReactModalShadowNode(); + } + + @Override + public Class getShadowNodeClass() { + return FlatReactModalShadowNode.class; + } +}