mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-17 04:41:36 +08:00
Merge pull request #1838 from NativeScript/feature/modal-dialog-imprvements
ShownModally fired when the dialog is actually shown in Android
This commit is contained in:
@ -28,6 +28,9 @@ import stackLayoutModule = require("ui/layouts/stack-layout");
|
||||
import helper = require("../helper");
|
||||
import view = require("ui/core/view");
|
||||
import observable = require("data/observable");
|
||||
import {Page, ShownModallyData} from "ui/page";
|
||||
import {Label} from "ui/label";
|
||||
import {EventData} from "data/observable";
|
||||
|
||||
export function addLabelToPage(page: PageModule.Page, text?: string) {
|
||||
var label = new LabelModule.Label();
|
||||
@ -440,6 +443,76 @@ export function test_WhenNavigatingForwardAndBack_IsBackNavigationIsCorrect() {
|
||||
helper.goBack();
|
||||
}
|
||||
|
||||
export function test_WhenPageIsNavigatedToItCanShowAnotherPageAsModal() {
|
||||
var masterPage;
|
||||
var ctx = {
|
||||
shownModally: false
|
||||
};
|
||||
|
||||
var modalClosed = false;
|
||||
var modalCloseCallback = function (returnValue: any) {
|
||||
TKUnit.assertTrue(ctx.shownModally, "Modal-page must be shown!");
|
||||
TKUnit.assertEqual(returnValue, "return value", "Modal-page must return value!");
|
||||
modalClosed = true;
|
||||
}
|
||||
|
||||
let modalPage: Page;
|
||||
|
||||
let shownModally = 0;
|
||||
var onShownModal = function (args: ShownModallyData) {
|
||||
shownModally++;
|
||||
modalPage.off(Page.shownModallyEvent, onShownModal);
|
||||
}
|
||||
|
||||
let modalLoaded = 0;
|
||||
var onModalLoaded = function (args: EventData) {
|
||||
modalLoaded++;
|
||||
modalPage.off(Page.loadedEvent, onModalLoaded);
|
||||
}
|
||||
|
||||
let modalUnloaded = 0;
|
||||
var onModalUnloaded = function (args: EventData) {
|
||||
modalUnloaded++;
|
||||
modalPage.off(Page.unloadedEvent, onModalUnloaded);
|
||||
TKUnit.assertNull(masterPage.modal, "currentPage.modal should be undefined when no modal page is shown!");
|
||||
}
|
||||
|
||||
var navigatedToEventHandler = function (args) {
|
||||
let page = <Page>args.object;
|
||||
TKUnit.assertNull(page.modal, "currentPage.modal should be undefined when no modal page is shown!");
|
||||
let basePath = "ui/page/";
|
||||
modalPage = page.showModal(basePath + "modal-page", ctx, modalCloseCallback, false);
|
||||
TKUnit.assertTrue((<any>modalPage).showingModally, "showingModally");
|
||||
modalPage.on(Page.shownModallyEvent, onShownModal);
|
||||
modalPage.on(Page.loadedEvent, onModalLoaded);
|
||||
modalPage.on(Page.unloadedEvent, onModalUnloaded);
|
||||
};
|
||||
|
||||
var masterPageFactory = function (): Page {
|
||||
masterPage = new Page();
|
||||
masterPage.id = "newPage";
|
||||
masterPage.on(Page.navigatedToEvent, navigatedToEventHandler);
|
||||
var label = new Label();
|
||||
label.text = "Text";
|
||||
masterPage.content = label;
|
||||
return masterPage;
|
||||
};
|
||||
|
||||
try {
|
||||
helper.navigate(masterPageFactory);
|
||||
|
||||
TKUnit.waitUntilReady(() => { return modalUnloaded > 0; });
|
||||
TKUnit.assertEqual(shownModally, 1, "shownModally");
|
||||
TKUnit.assertEqual(modalLoaded, 1, "modalLoaded");
|
||||
TKUnit.assertEqual(modalUnloaded, 1, "modalUnloaded");
|
||||
|
||||
masterPage.off(Page.navigatedToEvent, navigatedToEventHandler);
|
||||
}
|
||||
finally {
|
||||
helper.goBack();
|
||||
}
|
||||
}
|
||||
|
||||
//export function test_ModalPage_Layout_is_Correct() {
|
||||
// var testPage: PageModule.Page;
|
||||
// var label: LabelModule.Label;
|
||||
|
@ -1,5 +1,5 @@
|
||||
import PageTestCommon = require("./page-tests-common");
|
||||
import {Page, ShownModallyData} from "ui/page";
|
||||
import {Page} from "ui/page";
|
||||
import TKUnit = require("../../TKUnit");
|
||||
import {Label} from "ui/label";
|
||||
import helper = require("../helper");
|
||||
@ -27,76 +27,6 @@ export function test_NavigateToNewPage_InnerControl() {
|
||||
TKUnit.assertFalse(label.isLoaded, "label.isLoaded should become false after navigating back");
|
||||
}
|
||||
|
||||
export function test_WhenPageIsNavigatedToItCanShowAnotherPageAsModal() {
|
||||
var masterPage;
|
||||
var ctx = {
|
||||
shownModally: false
|
||||
};
|
||||
|
||||
var modalClosed = false;
|
||||
var modalCloseCallback = function (returnValue: any) {
|
||||
TKUnit.assertTrue(ctx.shownModally, "Modal-page must be shown!");
|
||||
TKUnit.assertEqual(returnValue, "return value", "Modal-page must return value!");
|
||||
modalClosed = true;
|
||||
}
|
||||
|
||||
let modalPage: Page;
|
||||
|
||||
let shownModally = 0;
|
||||
var onShownModal = function (args: ShownModallyData) {
|
||||
shownModally++;
|
||||
modalPage.off(Page.shownModallyEvent, onShownModal);
|
||||
}
|
||||
|
||||
let modalLoaded = 0;
|
||||
var onModalLoaded = function (args: EventData) {
|
||||
modalLoaded++;
|
||||
modalPage.off(Page.loadedEvent, onModalLoaded);
|
||||
}
|
||||
|
||||
let modalUnloaded = 0;
|
||||
var onModalUnloaded = function (args: EventData) {
|
||||
modalUnloaded++;
|
||||
modalPage.off(Page.unloadedEvent, onModalUnloaded);
|
||||
TKUnit.assertNull(masterPage.modal, "currentPage.modal should be undefined when no modal page is shown!");
|
||||
}
|
||||
|
||||
var navigatedToEventHandler = function (args) {
|
||||
let page = <Page>args.object;
|
||||
TKUnit.assertNull(page.modal, "currentPage.modal should be undefined when no modal page is shown!");
|
||||
let basePath = "ui/page/";
|
||||
modalPage = page.showModal(basePath + "modal-page", ctx, modalCloseCallback, false);
|
||||
TKUnit.assertTrue((<any>modalPage).showingModally, "showingModally");
|
||||
modalPage.on(Page.shownModallyEvent, onShownModal);
|
||||
modalPage.on(Page.loadedEvent, onModalLoaded);
|
||||
modalPage.on(Page.unloadedEvent, onModalUnloaded);
|
||||
};
|
||||
|
||||
var masterPageFactory = function (): Page {
|
||||
masterPage = new Page();
|
||||
masterPage.id = "newPage";
|
||||
masterPage.on(Page.navigatedToEvent, navigatedToEventHandler);
|
||||
var label = new Label();
|
||||
label.text = "Text";
|
||||
masterPage.content = label;
|
||||
return masterPage;
|
||||
};
|
||||
|
||||
try {
|
||||
helper.navigate(masterPageFactory);
|
||||
|
||||
TKUnit.waitUntilReady(() => { return modalUnloaded > 0; });
|
||||
TKUnit.assertEqual(shownModally, 1, "shownModally");
|
||||
TKUnit.assertEqual(modalLoaded, 1,"modalLoaded");
|
||||
TKUnit.assertEqual(modalUnloaded,1 , "modalUnloaded");
|
||||
|
||||
masterPage.off(Page.navigatedToEvent, navigatedToEventHandler);
|
||||
}
|
||||
finally {
|
||||
helper.goBack();
|
||||
}
|
||||
}
|
||||
|
||||
export function test_WhenShowingModalPageUnloadedIsNotFiredForTheMasterPage() {
|
||||
let masterPage: Page;
|
||||
let masterPageUnloaded = false;
|
||||
|
@ -50,6 +50,7 @@ export class Page extends ContentView implements dts.Page {
|
||||
public static showingModallyEvent = "showingModally";
|
||||
|
||||
protected _closeModalCallback: Function;
|
||||
private _modalContext: any;
|
||||
|
||||
private _navigationContext: any;
|
||||
|
||||
@ -250,9 +251,11 @@ export class Page extends ContentView implements dts.Page {
|
||||
protected _showNativeModalView(parent: Page, context: any, closeCallback: Function, fullscreen?: boolean) {
|
||||
parent._modal = this;
|
||||
var that = this;
|
||||
this._modalContext = context;
|
||||
this._closeModalCallback = function () {
|
||||
if (that._closeModalCallback) {
|
||||
that._closeModalCallback = null;
|
||||
that._modalContext = null;
|
||||
that._hideNativeModalView(parent);
|
||||
if (typeof closeCallback === "function") {
|
||||
closeCallback.apply(undefined, arguments);
|
||||
@ -265,20 +268,24 @@ export class Page extends ContentView implements dts.Page {
|
||||
//
|
||||
}
|
||||
|
||||
protected _raiseShownModallyEvent(parent: Page, context: any, closeCallback: Function) {
|
||||
this.notify({
|
||||
protected _raiseShownModallyEvent() {
|
||||
let args: dts.ShownModallyData = {
|
||||
eventName: Page.shownModallyEvent,
|
||||
object: this,
|
||||
context: context,
|
||||
context: this._modalContext,
|
||||
closeCallback: this._closeModalCallback
|
||||
});
|
||||
}
|
||||
this.notify(args);
|
||||
}
|
||||
|
||||
protected _raiseShowingModallyEvent() {
|
||||
this.notify({
|
||||
let args: dts.ShownModallyData = {
|
||||
eventName: Page.showingModallyEvent,
|
||||
object: this
|
||||
});
|
||||
object: this,
|
||||
context: this._modalContext,
|
||||
closeCallback: this._closeModalCallback
|
||||
}
|
||||
this.notify(args);
|
||||
}
|
||||
|
||||
public _getStyleScope(): styleScope.StyleScope {
|
||||
|
@ -25,23 +25,23 @@ function ensureColor() {
|
||||
|
||||
export var DIALOG_FRAGMENT_TAG = "dialog";
|
||||
|
||||
var DialogFragmentClass;
|
||||
function ensureDialogFragmentClass() {
|
||||
interface DialogFragmentClass {
|
||||
new (owner: Page, fullscreen: boolean, shownCallback: () => void, dismissCallback: () => void): android.app.DialogFragment;
|
||||
}
|
||||
var DialogFragmentClass: DialogFragmentClass;
|
||||
|
||||
function ensureDialogFragmentClass() {
|
||||
if (DialogFragmentClass) {
|
||||
return;
|
||||
}
|
||||
|
||||
class DialogFragmentClassInner extends android.app.DialogFragment {
|
||||
private _owner: Page;
|
||||
private _fullscreen: boolean;
|
||||
private _dismissCallback: Function;
|
||||
|
||||
constructor(owner: Page, fullscreen?: boolean, dismissCallback?: Function) {
|
||||
constructor(
|
||||
private _owner: Page,
|
||||
private _fullscreen: boolean,
|
||||
private _shownCallback: () => void,
|
||||
private _dismissCallback: () => void) {
|
||||
super();
|
||||
|
||||
this._owner = owner;
|
||||
this._fullscreen = fullscreen;
|
||||
this._dismissCallback = dismissCallback;
|
||||
return global.__native(this);
|
||||
}
|
||||
|
||||
@ -66,10 +66,29 @@ function ensureDialogFragmentClass() {
|
||||
return dialog;
|
||||
}
|
||||
|
||||
public onDismiss() {
|
||||
if (typeof this._dismissCallback === "function") {
|
||||
this._dismissCallback();
|
||||
public onStart() {
|
||||
super.onStart();
|
||||
if (!this._owner.isLoaded) {
|
||||
this._owner.onLoaded();
|
||||
}
|
||||
this._shownCallback();
|
||||
}
|
||||
|
||||
public onDestroyView() {
|
||||
super.onDestroyView();
|
||||
|
||||
if (this._owner.isLoaded) {
|
||||
this._owner.onUnloaded();
|
||||
}
|
||||
|
||||
this._owner._isAddedToNativeVisualTree = false;
|
||||
this._owner._onDetached(true);
|
||||
|
||||
}
|
||||
|
||||
public onDismiss(dialog: android.content.IDialogInterface) {
|
||||
super.onDismiss(dialog);
|
||||
this._dismissCallback();
|
||||
}
|
||||
|
||||
};
|
||||
@ -146,26 +165,20 @@ export class Page extends pageCommon.Page {
|
||||
|
||||
this._onAttached(parent._context);
|
||||
this._isAddedToNativeVisualTree = true;
|
||||
this.onLoaded();
|
||||
|
||||
ensureDialogFragmentClass();
|
||||
var that = this;
|
||||
this._dialogFragment = new DialogFragmentClass(this, fullscreen, function () {
|
||||
that.closeModal();
|
||||
});
|
||||
|
||||
this._dialogFragment = new DialogFragmentClass(this, !!fullscreen, () => this._raiseShownModallyEvent(), () => this.closeModal());
|
||||
|
||||
super._raiseShowingModallyEvent();
|
||||
|
||||
this._dialogFragment.show(parent.frame.android.activity.getFragmentManager(), DIALOG_FRAGMENT_TAG);
|
||||
super._raiseShownModallyEvent(parent, context, closeCallback);
|
||||
}
|
||||
|
||||
protected _hideNativeModalView(parent: Page) {
|
||||
this._dialogFragment.dismissAllowingStateLoss();
|
||||
this._dialogFragment = null;
|
||||
|
||||
this.onUnloaded();
|
||||
this._isAddedToNativeVisualTree = false;
|
||||
this._onDetached(true);
|
||||
parent._modal = undefined;
|
||||
|
||||
super._hideNativeModalView(parent);
|
||||
|
2
ui/page/page.d.ts
vendored
2
ui/page/page.d.ts
vendored
@ -166,7 +166,7 @@ declare module "ui/page" {
|
||||
/**
|
||||
* Raised before the page is shown as a modal dialog.
|
||||
*/
|
||||
on(event: "showingModally", callback: (args: observable.EventData) => void, thisArg?: any): void;
|
||||
on(event: "showingModally", callback: (args: ShownModallyData) => void, thisArg?: any): void;
|
||||
|
||||
/**
|
||||
* Raised after the page is shown as a modal dialog.
|
||||
|
@ -340,7 +340,7 @@ export class Page extends pageCommon.Page {
|
||||
var that = this;
|
||||
parent.ios.presentViewControllerAnimatedCompletion(this._ios, utils.ios.MajorVersion >= 8, null);
|
||||
UIViewControllerTransitionCoordinator.prototype.animateAlongsideTransitionCompletion.call(parent.ios.transitionCoordinator(), null, function () {
|
||||
that._raiseShownModallyEvent(parent, context, closeCallback);
|
||||
that._raiseShownModallyEvent();
|
||||
});
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user