Permalink
Browse files

Support orientation change on modals

Summary:
This automatically changes the size of the modal by listening to dialog size changes and propagating
those changes through UIManager.

In detail: I've looked into three ways of doing this:

1. Send `onSizeChanged` events/info from the View to the CSSNode directly. This is kinda hacky because you would need to hold a reference to the CSSNode somewhere, either in the View or in the ViewManager. But then you'll have to take care of the lifecycle of the CSSNode, so that you don't update it after it has been dismissed. Not great.
2. The version we went for, is to just update the size of the corresponding CSSNode in the same way we do it for root nodes: we inform the UIManager that the size of the root node has changed, and it will propagate that change, triggering a `dispatchViewUpdates` if none is underway, so that the layout is updated.
3. The other solution we thought of is to treat the Modal as a root view. This would mean rendering an application with the tag of the Modal as the root of the application. That tag would be received by calling some method into UIManager and ReactModalHostManager to create a new RootView, create a Dialog and plop the root view in it. The idea was to maintain the JS API that we now have, but make the implementation more correct (ie. since both RootView and the Modal must deal with touch handling), and could have other benefits (ie. no hacks necessary for making the inspector work on top of modals). However, the change is not trivial and I don't know just how much code would have to be changed to make this work correctly. We might revisit this at a later stage, after we've done more work on having several root views at the same time in the app.

Reviewed By: foghina

Differential Revision: D3841379

fbshipit-source-id: f5e363e27041b785cf44eb59da04bc789306ddb9
  • Loading branch information...
1 parent 178407d commit 82c8c97898c2ba7fbe7e371249354d353b1d4161 @andreicoman11 andreicoman11 committed with Facebook Github Bot 4 Sep 13, 2016
@@ -130,16 +130,17 @@ public void removeRootView(int rootViewTag) {
}
/**
- * Invoked when native view that corresponds to a root node has its size changed.
+ * Invoked when native view that corresponds to a root node, or acts as a root view (ie. Modals)
+ * has its size changed.
*/
- public void updateRootNodeSize(
- int rootViewTag,
+ public void updateNodeSize(
+ int nodeViewTag,
int newWidth,
int newHeight,
EventDispatcher eventDispatcher) {
- ReactShadowNode rootCSSNode = mShadowNodeRegistry.getNode(rootViewTag);
- rootCSSNode.setStyleWidth(newWidth);
- rootCSSNode.setStyleHeight(newHeight);
+ ReactShadowNode cssNode = mShadowNodeRegistry.getNode(nodeViewTag);
+ cssNode.setStyleWidth(newWidth);
+ cssNode.setStyleHeight(newHeight);
// If we're in the middle of a batch, the change will automatically be dispatched at the end of
// the batch. As all batches are executed as a single runnable on the event queue this should
@@ -192,7 +192,7 @@ public void onSizeChanged(final int width, final int height, int oldW, int oldH)
new Runnable() {
@Override
public void run() {
- updateRootNodeSize(tag, width, height);
+ updateNodeSize(tag, width, height);
}
});
}
@@ -206,10 +206,10 @@ public void removeRootView(int rootViewTag) {
mUIImplementation.removeRootView(rootViewTag);
}
- private void updateRootNodeSize(int rootViewTag, int newWidth, int newHeight) {
+ public void updateNodeSize(int nodeViewTag, int newWidth, int newHeight) {
getReactApplicationContext().assertOnNativeModulesQueueThread();
- mUIImplementation.updateRootNodeSize(rootViewTag, newWidth, newHeight, mEventDispatcher);
+ mUIImplementation.updateNodeSize(nodeViewTag, newWidth, newHeight, mEventDispatcher);
}
@ReactMethod
@@ -265,6 +265,21 @@ public DialogRootViewGroup(Context context) {
}
@Override
+ protected void onSizeChanged(final int w, final int h, int oldw, int oldh) {
+ super.onSizeChanged(w, h, oldw, oldh);
+ if (getChildCount() > 0) {
+ ((ReactContext) getContext()).runOnNativeModulesQueueThread(
+ new Runnable() {
+ @Override
+ public void run() {
+ ((ReactContext) getContext()).getNativeModule(UIManagerModule.class)
+ .updateNodeSize(getChildAt(0).getId(), w, h);
+ }
+ });
+ }
+ }
+
+ @Override
public boolean onInterceptTouchEvent(MotionEvent event) {
mJSTouchDispatcher.handleTouchEvent(event, getEventDispatcher());
return super.onInterceptTouchEvent(event);

0 comments on commit 82c8c97

Please sign in to comment.