Fix modal size
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:
Родитель
a36ccf227d
Коммит
4941cbcf1e
|
@ -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.bridge.ReactApplicationContext;
|
||||||
import com.facebook.react.common.MapBuilder;
|
import com.facebook.react.common.MapBuilder;
|
||||||
import com.facebook.react.uimanager.LayoutShadowNode;
|
|
||||||
import com.facebook.react.uimanager.PixelUtil;
|
import com.facebook.react.uimanager.PixelUtil;
|
||||||
import com.facebook.react.uimanager.ThemedReactContext;
|
import com.facebook.react.uimanager.ThemedReactContext;
|
||||||
import com.facebook.react.uimanager.UIManagerModule;
|
import com.facebook.react.uimanager.UIManagerModule;
|
||||||
|
@ -48,16 +47,6 @@ public class ReactModalHostManager extends ViewGroupManager<ReactModalHostView>
|
||||||
return new ReactModalHostView(reactContext);
|
return new ReactModalHostView(reactContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public LayoutShadowNode createShadowNodeInstance() {
|
|
||||||
return new ModalHostShadowNode();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<? extends LayoutShadowNode> getShadowNodeClass() {
|
|
||||||
return ModalHostShadowNode.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDropViewInstance(ReactModalHostView view) {
|
public void onDropViewInstance(ReactModalHostView view) {
|
||||||
super.onDropViewInstance(view);
|
super.onDropViewInstance(view);
|
||||||
|
@ -112,8 +101,7 @@ public class ReactModalHostManager extends ViewGroupManager<ReactModalHostView>
|
||||||
0;
|
0;
|
||||||
|
|
||||||
return MapBuilder.<String, Object>of(
|
return MapBuilder.<String, Object>of(
|
||||||
"StatusBarHeight", height
|
"StatusBarHeight", height);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -16,8 +16,11 @@ import java.util.ArrayList;
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
|
import android.graphics.Point;
|
||||||
|
import android.view.Display;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
|
import android.view.Surface;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.WindowManager;
|
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
|
* 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
|
* also responsible for acting as a RootView and handling touch events. It does this the same
|
||||||
* way as ReactRootView.
|
* 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 {
|
static class DialogRootViewGroup extends ReactViewGroup implements RootView {
|
||||||
|
|
||||||
private final JSTouchDispatcher mJSTouchDispatcher = new JSTouchDispatcher(this);
|
private final JSTouchDispatcher mJSTouchDispatcher = new JSTouchDispatcher(this);
|
||||||
|
private final Point mMinPoint = new Point();
|
||||||
|
private final Point mMaxPoint = new Point();
|
||||||
|
|
||||||
public DialogRootViewGroup(Context context) {
|
public DialogRootViewGroup(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
|
@ -272,8 +282,33 @@ public class ReactModalHostView extends ViewGroup implements LifecycleEventListe
|
||||||
new Runnable() {
|
new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
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)
|
((ReactContext) getContext()).getNativeModule(UIManagerModule.class)
|
||||||
.updateNodeSize(getChildAt(0).getId(), w, h);
|
.updateNodeSize(getChildAt(0).getId(), width, height);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче