Summary:
With our previous fix to resize the Modal on orientation change, we broke the
computation of its size. The existing computation in `ModalHostShadowNode` was
in fact correct, and we were overriding it from `onSizeChanged`. By computing the
size of the Modal in `onSizeChanged` directly (and correctly), we fix this, and
simplify code by removing the `ModalHostShadowNode`.

Reviewed By: foghina

Differential Revision: D3863054

fbshipit-source-id: aaf4a8881798df4d2ab1dab882a9d9dfdc0a9342
This commit is contained in:
Andrei Coman 2016-09-19 02:46:04 -07:00 коммит произвёл Facebook Github Bot
Родитель a36ccf227d
Коммит 4941cbcf1e
3 изменённых файлов: 37 добавлений и 82 удалений

Просмотреть файл

@ -1,68 +0,0 @@
/**
* 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.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;
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.
*
* To get that we use information from the WindowManager and default Display. We don't use
* DisplayMetricsHolder because it returns values that include the status bar. We only want the
* values of what will actually be shown on screen.
*/
class ModalHostShadowNode extends LayoutShadowNode {
private final Point mMinPoint = new Point();
private final Point mMaxPoint = new Point();
/**
* We need to set the styleWidth and styleHeight of the one child (represented by the <View/>
* within the <RCTModalHostView/> 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);
}
}

Просмотреть файл

@ -17,7 +17,6 @@ import android.content.DialogInterface;
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;
@ -48,16 +47,6 @@ public class ReactModalHostManager extends ViewGroupManager<ReactModalHostView>
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);
@ -112,8 +101,7 @@ public class ReactModalHostManager extends ViewGroupManager<ReactModalHostView>
0;
return MapBuilder.<String, Object>of(
"StatusBarHeight", height
);
"StatusBarHeight", height);
}
@Override

Просмотреть файл

@ -16,8 +16,11 @@ import java.util.ArrayList;
import android.app.Dialog;
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;
@ -255,10 +258,17 @@ public class ReactModalHostView extends ViewGroup implements LifecycleEventListe
* child information forwarded from ReactModalHostView and uses that to create children. It is
* also responsible for acting as a RootView and handling touch events. It does this the same
* way as ReactRootView.
*
* To get layout to work properly, we need to layout all the elements within the Modal as if they
* can fill the entire window. To do that, we need to explicitly set the styleWidth and
* styleHeight on the LayoutShadowNode to be the window size. This is done through the
* UIManagerModule, and will then cause the children to layout as if they can fill the window.
*/
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);
@ -272,8 +282,33 @@ public class ReactModalHostView extends ViewGroup implements LifecycleEventListe
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;
}
((ReactContext) getContext()).getNativeModule(UIManagerModule.class)
.updateNodeSize(getChildAt(0).getId(), w, h);
.updateNodeSize(getChildAt(0).getId(), width, height);
}
});
}