Merge pull request #3543 from NativeScript/fix-modal-crashes

Fix: Modal crashes in Android and IOS
This commit is contained in:
Alexander Vakrilov
2017-02-01 10:03:50 +02:00
committed by GitHub
5 changed files with 34 additions and 46 deletions

View File

@ -291,7 +291,7 @@ typedExports.start = function (entry?: NavigationEntry) {
if(window) { if(window) {
var rootController = window.rootViewController; var rootController = window.rootViewController;
if(rootController) { if(rootController) {
rootController.presentViewControllerAnimatedCompletion(rootView.ios.controller, utils.ios.MajorVersion >= 7, null); rootController.presentViewControllerAnimatedCompletion(rootView.ios.controller, true, null);
uiUtils.ios._layoutRootView(rootView, utils.ios.getter(UIScreen, UIScreen.mainScreen).bounds); uiUtils.ios._layoutRootView(rootView, utils.ios.getter(UIScreen, UIScreen.mainScreen).bounds);
} }
} }

View File

@ -155,20 +155,7 @@ export class View extends ViewCommon {
return; return;
} }
// This is done because when rotated in iOS7 there is rotation applied on the first subview on the Window which is our frame.nativeView.view.
// // If we set it it should be transformed so it is correct.
// // When in landscape in iOS 7 there is transformation on the first subview of the window so we set frame to its subview.
// // in iOS 8 we set frame to subview again otherwise we get clipped.
// let nativeView: UIView;
// if (!this.parent && this.nativeView.subviews.count > 0 && ios.MajorVersion < 8) {
// if (traceEnabled()) {
// traceWrite(this + " has no parent. Setting frame to first child instead.", traceCategories.Layout);
// }
// nativeView = (<UIView>this.nativeView.subviews[0]);
// }
// else {
let nativeView = this.nativeView; let nativeView = this.nativeView;
// }
let frame = CGRectMake(left, top, right - left, bottom - top); let frame = CGRectMake(left, top, right - left, bottom - top);
this._setNativeViewFrame(nativeView, frame); this._setNativeViewFrame(nativeView, frame);

View File

@ -8,6 +8,8 @@ import { isString, isDefined, isFunction } from "utils/types";
import * as utils from "utils/utils"; import * as utils from "utils/utils";
import getter = utils.ios.getter; import getter = utils.ios.getter;
export * from "./dialogs-common";
class UIAlertViewDelegateImpl extends NSObject implements UIAlertViewDelegate { class UIAlertViewDelegateImpl extends NSObject implements UIAlertViewDelegate {
public static ObjCProtocols = [UIAlertViewDelegate]; public static ObjCProtocols = [UIAlertViewDelegate];

View File

@ -39,7 +39,13 @@ function ensureDialogFragmentClass() {
this._owner.verticalAlignment = this._fullscreen ? VerticalAlignment.STRETCH : VerticalAlignment.MIDDLE; this._owner.verticalAlignment = this._fullscreen ? VerticalAlignment.STRETCH : VerticalAlignment.MIDDLE;
this._owner.actionBarHidden = true; this._owner.actionBarHidden = true;
dialog.setContentView(this._owner._nativeView, this._owner._nativeView.getLayoutParams()); const nativeView = <android.view.View>this._owner._nativeView;
let layoutParams = nativeView.getLayoutParams();
if (!layoutParams) {
layoutParams = new org.nativescript.widgets.CommonLayoutParams();
nativeView.setLayoutParams(layoutParams);
}
dialog.setContentView(this._owner._nativeView, layoutParams);
const window = dialog.getWindow(); const window = dialog.getWindow();
window.setBackgroundDrawable(new android.graphics.drawable.ColorDrawable(android.graphics.Color.TRANSPARENT)); window.setBackgroundDrawable(new android.graphics.drawable.ColorDrawable(android.graphics.Color.TRANSPARENT));

View File

@ -84,9 +84,12 @@ class UIViewControllerImpl extends UIViewController {
return; return;
} }
if (owner._modalParent) { const modalParent = owner._modalParent;
let isTablet = device.deviceType === "Tablet"; if (modalParent) {
let isFullScreen = !owner._UIModalPresentationFormSheet || !isTablet; // if inside horizontally compact environment - fullScreen will be forced
let isFullScreen = !owner._UIModalPresentationFormSheet ||
(modalParent.nativeView.traitCollection.horizontalSizeClass === UIUserInterfaceSizeClass.Compact);
let frame = isFullScreen ? getter(UIScreen, UIScreen.mainScreen).bounds : this.view.frame; let frame = isFullScreen ? getter(UIScreen, UIScreen.mainScreen).bounds : this.view.frame;
let size = frame.size; let size = frame.size;
let width = size.width; let width = size.width;
@ -99,12 +102,6 @@ class UIViewControllerImpl extends UIViewController {
superViewRotationRadians = atan2f(transform.b, transform.a); superViewRotationRadians = atan2f(transform.b, transform.a);
} }
if (ios.MajorVersion < 8 && ios.isLandscape() && !superViewRotationRadians) {
// in iOS 7 when in landscape we switch width with height because on device they don't change even when rotated.
width = size.height;
height = size.width;
}
let bottom = height; let bottom = height;
let statusBarHeight = uiUtils.ios.getStatusBarHeight(); let statusBarHeight = uiUtils.ios.getStatusBarHeight();
let statusBarVisible = !getter(UIApplication, UIApplication.sharedApplication).statusBarHidden; let statusBarVisible = !getter(UIApplication, UIApplication.sharedApplication).statusBarHidden;
@ -116,20 +113,9 @@ class UIViewControllerImpl extends UIViewController {
let widthSpec = layout.makeMeasureSpec(width, mode); let widthSpec = layout.makeMeasureSpec(width, mode);
let heightSpec = layout.makeMeasureSpec(height, mode); let heightSpec = layout.makeMeasureSpec(height, mode);
View.measureChild(owner._modalParent, owner, widthSpec, heightSpec); View.measureChild(modalParent, owner, widthSpec, heightSpec);
let top = ((backgroundSpanUnderStatusBar && isFullScreen) || ios.MajorVersion < 8 || !isFullScreen) ? 0 : statusBarHeight; let top = ((backgroundSpanUnderStatusBar && isFullScreen) || !isFullScreen) ? 0 : statusBarHeight;
View.layoutChild(owner._modalParent, owner, 0, top, width, bottom); View.layoutChild(modalParent, owner, 0, top, width, bottom);
if (ios.MajorVersion < 8) {
if (!backgroundSpanUnderStatusBar && (!isTablet || isFullScreen)) {
if (ios.isLandscape() && !superViewRotationRadians) {
this.view.center = CGPointMake(this.view.center.x - statusBarHeight, this.view.center.y);
}
else {
this.view.center = CGPointMake(this.view.center.x, this.view.center.y + statusBarHeight);
}
}
}
if (traceEnabled()) { if (traceEnabled()) {
traceWrite(owner + ", native frame = " + NSStringFromCGRect(this.view.frame), traceCategories.Layout); traceWrite(owner + ", native frame = " + NSStringFromCGRect(this.view.frame), traceCategories.Layout);
@ -156,8 +142,9 @@ class UIViewControllerImpl extends UIViewController {
return; return;
} }
let frame = this.navigationController ? (<any>this.navigationController).owner : null; const frame = this.navigationController ? (<any>this.navigationController).owner : null;
let newEntry = this[ENTRY]; const newEntry = this[ENTRY];
const modalParent = page._modalParent;
// Don't raise event if currentPage was showing modal page. // Don't raise event if currentPage was showing modal page.
if (!page._presentedViewController && newEntry && (!frame || frame.currentPage !== page)) { if (!page._presentedViewController && newEntry && (!frame || frame.currentPage !== page)) {
@ -167,6 +154,11 @@ class UIViewControllerImpl extends UIViewController {
page._enableLoadedEvents = true; page._enableLoadedEvents = true;
// Add page to frame if showing modal page.
if (modalParent) {
modalParent.frame._addView(page);
}
if (frame) { if (frame) {
if (!page.parent) { if (!page.parent) {
if (!frame._currentEntry) { if (!frame._currentEntry) {
@ -279,7 +271,7 @@ class UIViewControllerImpl extends UIViewController {
public viewDidDisappear(animated: boolean): void { public viewDidDisappear(animated: boolean): void {
super.viewDidDisappear(animated); super.viewDidDisappear(animated);
let page = this._owner.get(); const page = this._owner.get();
if (traceEnabled()) { if (traceEnabled()) {
traceWrite(page + " viewDidDisappear", traceCategories.Navigation); traceWrite(page + " viewDidDisappear", traceCategories.Navigation);
} }
@ -288,12 +280,13 @@ class UIViewControllerImpl extends UIViewController {
return; return;
} }
let modalParent = page._modalParent; const modalParent = page._modalParent;
page._modalParent = undefined; page._modalParent = undefined;
page._UIModalPresentationFormSheet = false; page._UIModalPresentationFormSheet = false;
// Clear modal flag on parent page. // Clear up after modal page has closed.
if (modalParent) { if (modalParent) {
modalParent.frame._removeView(page);
modalParent._modal = undefined; modalParent._modal = undefined;
} }
@ -430,7 +423,7 @@ export class Page extends PageBase {
super._raiseShowingModallyEvent(); super._raiseShowingModallyEvent();
parent.ios.presentViewControllerAnimatedCompletion(this._ios, ios.MajorVersion >= 7, null); parent.ios.presentViewControllerAnimatedCompletion(this._ios, true, null);
let transitionCoordinator = getter(parent.ios, parent.ios.transitionCoordinator); let transitionCoordinator = getter(parent.ios, parent.ios.transitionCoordinator);
if (transitionCoordinator) { if (transitionCoordinator) {
UIViewControllerTransitionCoordinator.prototype.animateAlongsideTransitionCompletion.call(transitionCoordinator, null, () => this._raiseShownModallyEvent()); UIViewControllerTransitionCoordinator.prototype.animateAlongsideTransitionCompletion.call(transitionCoordinator, null, () => this._raiseShownModallyEvent());
@ -445,7 +438,7 @@ export class Page extends PageBase {
protected _hideNativeModalView(parent: Page) { protected _hideNativeModalView(parent: Page) {
parent.requestLayout(); parent.requestLayout();
parent._ios.dismissModalViewControllerAnimated(ios.MajorVersion >= 7); parent._ios.dismissModalViewControllerAnimated(true);
super._hideNativeModalView(parent); super._hideNativeModalView(parent);
} }
@ -520,7 +513,7 @@ export class Page extends PageBase {
statusBarHeight = 0; statusBarHeight = 0;
} }
if (this.frame && this.frame._getNavBarVisible(this)) { if (!this._modalParent && this.frame && this.frame._getNavBarVisible(this)) {
// Measure ActionBar with the full height. // Measure ActionBar with the full height.
let actionBarSize = View.measureChild(this, this.actionBar, widthMeasureSpec, heightMeasureSpec); let actionBarSize = View.measureChild(this, this.actionBar, widthMeasureSpec, heightMeasureSpec);
actionBarWidth = actionBarSize.measuredWidth; actionBarWidth = actionBarSize.measuredWidth;