Merge pull request #1529 from NativeScript/trans

Re-factored page navigation transitions. Resolves Issue #811.
This commit is contained in:
Rossen Hristov
2016-02-10 15:20:25 +02:00
10 changed files with 97 additions and 57 deletions

View File

@ -171,12 +171,12 @@ export class NavPage extends Page implements definition.ControlsPage {
var customTransitionModule = require("./custom-transition"); var customTransitionModule = require("./custom-transition");
var customTransition = new customTransitionModule.CustomTransition(duration, curve); var customTransition = new customTransitionModule.CustomTransition(duration, curve);
navigationTransition = { navigationTransition = {
transition: customTransition instance: customTransition
}; };
} }
else { else {
navigationTransition = { navigationTransition = {
transition: transitionName, name: transitionName,
duration: duration, duration: duration,
curve: curve curve: curve
}; };
@ -188,7 +188,7 @@ export class NavPage extends Page implements definition.ControlsPage {
backstackVisible: addToBackStackSwitch.checked, backstackVisible: addToBackStackSwitch.checked,
clearHistory: clearHistorySwitch.checked, clearHistory: clearHistorySwitch.checked,
animated: animatedSwitch.checked, animated: animatedSwitch.checked,
navigationTransition: navigationTransition, transition: navigationTransition,
}); });
}); });
stackLayout.addChild(forwardButton); stackLayout.addChild(forwardButton);

View File

@ -25,7 +25,7 @@ function _testTransition(navigationTransition: NavigationTransition) {
return page; return page;
}, },
animated: true, animated: true,
navigationTransition: navigationTransition transition: navigationTransition
} }
helper.navigateWithEntry(navigationEntry); helper.navigateWithEntry(navigationEntry);
@ -65,7 +65,7 @@ export var test_Transitions = function () {
for (d = 0; d < dlen; d++) { for (d = 0; d < dlen; d++) {
for (c = 0; c < clen; c++) { for (c = 0; c < clen; c++) {
_testTransition({ _testTransition({
transition: transitions[t], name: transitions[t],
duration: durations[d], duration: durations[d],
curve: curves[c] curve: curves[c]
}); });
@ -76,7 +76,7 @@ export var test_Transitions = function () {
// Custom transition // Custom transition
var customTransitionModule = require("./custom-transition"); var customTransitionModule = require("./custom-transition");
var customTransition = new customTransitionModule.CustomTransition(); var customTransition = new customTransitionModule.CustomTransition();
_testTransition({transition: customTransition}); _testTransition({ instance: customTransition });
helper.goBack(); helper.goBack();
} }

View File

@ -191,14 +191,14 @@ function _test_PageNavigation_EventSequence(withTransition: boolean) {
if (withTransition) { if (withTransition) {
var navigationTransition: FrameModule.NavigationTransition = { var navigationTransition: FrameModule.NavigationTransition = {
transition: "slide", name: "slide",
duration: 1000, duration: 1000,
}; };
var navigationEntry: FrameModule.NavigationEntry = { var navigationEntry: FrameModule.NavigationEntry = {
create: pageFactory, create: pageFactory,
context: context, context: context,
animated: true, animated: true,
navigationTransition: navigationTransition transition: navigationTransition
} }
helper.navigateWithEntry(navigationEntry); helper.navigateWithEntry(navigationEntry);
} }

View File

@ -53,7 +53,6 @@
"apps/connectivity-demo/app.ts", "apps/connectivity-demo/app.ts",
"apps/connectivity-demo/main-page.ts", "apps/connectivity-demo/main-page.ts",
"apps/custom-root-view/app.ts", "apps/custom-root-view/app.ts",
"apps/custom-root-view/list-view.ts",
"apps/cuteness.io/app.ts", "apps/cuteness.io/app.ts",
"apps/cuteness.io/details-page.ts", "apps/cuteness.io/details-page.ts",
"apps/cuteness.io/main-page.ts", "apps/cuteness.io/main-page.ts",
@ -91,16 +90,10 @@
"apps/perf-tests/ApplicationLoadTimeAndFPS/mainPage.ts", "apps/perf-tests/ApplicationLoadTimeAndFPS/mainPage.ts",
"apps/perf-tests/ApplicationSize/app.ts", "apps/perf-tests/ApplicationSize/app.ts",
"apps/perf-tests/ApplicationSize/mainPage.ts", "apps/perf-tests/ApplicationSize/mainPage.ts",
"apps/perf-tests/common.d.ts",
"apps/perf-tests/common.ts",
"apps/perf-tests/ComplexObjectGraphMemoryTest/app.ts", "apps/perf-tests/ComplexObjectGraphMemoryTest/app.ts",
"apps/perf-tests/ComplexObjectGraphMemoryTest/mainPage.ts", "apps/perf-tests/ComplexObjectGraphMemoryTest/mainPage.ts",
"apps/perf-tests/ControlCreationSpeedTest/app.ts", "apps/perf-tests/ControlCreationSpeedTest/app.ts",
"apps/perf-tests/ControlCreationSpeedTest/mainPage.ts", "apps/perf-tests/ControlCreationSpeedTest/mainPage.ts",
"apps/perf-tests/controls-page.d.ts",
"apps/perf-tests/controls-page.ts",
"apps/perf-tests/custom-transition.android.ts",
"apps/perf-tests/custom-transition.ios.ts",
"apps/perf-tests/LargeObjectArrayMemoryLeakTest/app.ts", "apps/perf-tests/LargeObjectArrayMemoryLeakTest/app.ts",
"apps/perf-tests/LargeObjectArrayMemoryLeakTest/mainPage.ts", "apps/perf-tests/LargeObjectArrayMemoryLeakTest/mainPage.ts",
"apps/perf-tests/LargeObjectArrayMemoryLeakTest/native-calls-wrapper.android.ts", "apps/perf-tests/LargeObjectArrayMemoryLeakTest/native-calls-wrapper.android.ts",
@ -108,8 +101,6 @@
"apps/perf-tests/LargeObjectArrayMemoryLeakTest/native-calls-wrapper.ios.ts", "apps/perf-tests/LargeObjectArrayMemoryLeakTest/native-calls-wrapper.ios.ts",
"apps/perf-tests/LargeObjectArrayMemoryTest/app.ts", "apps/perf-tests/LargeObjectArrayMemoryTest/app.ts",
"apps/perf-tests/LargeObjectArrayMemoryTest/mainPage.ts", "apps/perf-tests/LargeObjectArrayMemoryTest/mainPage.ts",
"apps/perf-tests/nav-page.d.ts",
"apps/perf-tests/nav-page.ts",
"apps/perf-tests/NavigationMemoryLeakTest/app.ts", "apps/perf-tests/NavigationMemoryLeakTest/app.ts",
"apps/perf-tests/NavigationMemoryLeakTest/mainPage.ts", "apps/perf-tests/NavigationMemoryLeakTest/mainPage.ts",
"apps/perf-tests/NavigationTest/app.ts", "apps/perf-tests/NavigationTest/app.ts",
@ -127,6 +118,14 @@
"apps/perf-tests/SpeedTests/tests-native.ios.ts", "apps/perf-tests/SpeedTests/tests-native.ios.ts",
"apps/perf-tests/SpeedTests/tests.d.ts", "apps/perf-tests/SpeedTests/tests.d.ts",
"apps/perf-tests/SpeedTests/tests.ts", "apps/perf-tests/SpeedTests/tests.ts",
"apps/perf-tests/common.d.ts",
"apps/perf-tests/common.ts",
"apps/perf-tests/controls-page.d.ts",
"apps/perf-tests/controls-page.ts",
"apps/perf-tests/custom-transition.android.ts",
"apps/perf-tests/custom-transition.ios.ts",
"apps/perf-tests/nav-page.d.ts",
"apps/perf-tests/nav-page.ts",
"apps/pickers-demo/app.ts", "apps/pickers-demo/app.ts",
"apps/pickers-demo/main-page.ts", "apps/pickers-demo/main-page.ts",
"apps/pickers-demo/model.ts", "apps/pickers-demo/model.ts",
@ -149,6 +148,7 @@
"apps/template-settings/view-model.ts", "apps/template-settings/view-model.ts",
"apps/template-tab-navigation/app.ts", "apps/template-tab-navigation/app.ts",
"apps/template-tab-navigation/main-page.ts", "apps/template-tab-navigation/main-page.ts",
"apps/tests/TKUnit.ts",
"apps/tests/app/app.ts", "apps/tests/app/app.ts",
"apps/tests/app/location-example.ts", "apps/tests/app/location-example.ts",
"apps/tests/app/mainPage.ts", "apps/tests/app/mainPage.ts",
@ -225,13 +225,12 @@
"apps/tests/testRunner.ts", "apps/tests/testRunner.ts",
"apps/tests/text/formatted-string-tests.ts", "apps/tests/text/formatted-string-tests.ts",
"apps/tests/timer-tests.ts", "apps/tests/timer-tests.ts",
"apps/tests/TKUnit.ts",
"apps/tests/trace-tests.ts", "apps/tests/trace-tests.ts",
"apps/tests/ui-test.ts", "apps/tests/ui-test.ts",
"apps/tests/ui/action-bar/ActionBar_NumberAsText.ts",
"apps/tests/ui/action-bar/action-bar-tests-common.ts", "apps/tests/ui/action-bar/action-bar-tests-common.ts",
"apps/tests/ui/action-bar/action-bar-tests.android.ts", "apps/tests/ui/action-bar/action-bar-tests.android.ts",
"apps/tests/ui/action-bar/action-bar-tests.ios.ts", "apps/tests/ui/action-bar/action-bar-tests.ios.ts",
"apps/tests/ui/action-bar/ActionBar_NumberAsText.ts",
"apps/tests/ui/activity-indicator/activity-indicator-tests.ts", "apps/tests/ui/activity-indicator/activity-indicator-tests.ts",
"apps/tests/ui/animation/animation-tests.ts", "apps/tests/ui/animation/animation-tests.ts",
"apps/tests/ui/bindable-tests.ts", "apps/tests/ui/bindable-tests.ts",

View File

@ -6,6 +6,7 @@ import * as trace from "trace";
import {resolveFileName} from "file-system/file-name-resolver"; import {resolveFileName} from "file-system/file-name-resolver";
import * as fs from "file-system"; import * as fs from "file-system";
import * as builderModule from "ui/builder"; import * as builderModule from "ui/builder";
import * as platform from "platform";
var builder: typeof builderModule; var builder: typeof builderModule;
function ensureBuilder() { function ensureBuilder() {
@ -138,11 +139,11 @@ export class Frame extends CustomLayoutView implements definition.Frame {
private _backStack: Array<definition.BackstackEntry>; private _backStack: Array<definition.BackstackEntry>;
public _currentEntry: definition.BackstackEntry; public _currentEntry: definition.BackstackEntry;
private _animated: boolean; private _animated: boolean;
private _navigationTransition: definition.NavigationTransition; private _transition: definition.NavigationTransition;
public _isInFrameStack = false; public _isInFrameStack = false;
public static defaultAnimatedNavigation = true; public static defaultAnimatedNavigation = true;
public static defaultNavigationTransition: definition.NavigationTransition; public static defaultTransition: definition.NavigationTransition;
// TODO: Currently our navigation will not be synchronized in case users directly call native navigation methods like Activity.startActivity. // TODO: Currently our navigation will not be synchronized in case users directly call native navigation methods like Activity.startActivity.
@ -325,12 +326,12 @@ export class Frame extends CustomLayoutView implements definition.Frame {
this._animated = value; this._animated = value;
} }
public get navigationTransition(): definition.NavigationTransition { public get transition(): definition.NavigationTransition {
return this._navigationTransition; return this._transition;
} }
public set navigationTransition(value: definition.NavigationTransition) { public set transition(value: definition.NavigationTransition) {
this._navigationTransition = value; this._transition = value;
} }
get backStack(): Array<definition.BackstackEntry> { get backStack(): Array<definition.BackstackEntry> {
@ -399,15 +400,25 @@ export class Frame extends CustomLayoutView implements definition.Frame {
} }
public _getNavigationTransition(entry: definition.NavigationEntry): definition.NavigationTransition { public _getNavigationTransition(entry: definition.NavigationEntry): definition.NavigationTransition {
if (entry && isDefined(entry.navigationTransition)) { if (entry) {
return entry.navigationTransition; if (platform.device.os === platform.platformNames.ios && isDefined(entry.transitioniOS)) {
return entry.transitioniOS;
}
if (platform.device.os === platform.platformNames.android && isDefined(entry.transitionAndroid)) {
return entry.transitioniOS;
}
if (entry && isDefined(entry.transition)) {
return entry.transition;
}
} }
if (isDefined(this.navigationTransition)) { if (isDefined(this.transition)) {
return this.navigationTransition; return this.transition;
} }
return Frame.defaultNavigationTransition; return Frame.defaultTransition;
} }
public get navigationBarHeight(): number { public get navigationBarHeight(): number {

View File

@ -202,11 +202,11 @@ export class Frame extends frameCommon.Frame {
frameCommon.Frame.defaultAnimatedNavigation = value; frameCommon.Frame.defaultAnimatedNavigation = value;
} }
public static get defaultNavigationTransition(): definition.NavigationTransition { public static get defaultTransition(): definition.NavigationTransition {
return frameCommon.Frame.defaultNavigationTransition; return frameCommon.Frame.defaultTransition;
} }
public static set defaultNavigationTransition(value: definition.NavigationTransition) { public static set defaultTransition(value: definition.NavigationTransition) {
frameCommon.Frame.defaultNavigationTransition = value; frameCommon.Frame.defaultTransition = value;
} }
get containerViewId(): number { get containerViewId(): number {

41
ui/frame/frame.d.ts vendored
View File

@ -5,6 +5,7 @@ declare module "ui/frame" {
import view = require("ui/core/view"); import view = require("ui/core/view");
import observable = require("data/observable"); import observable = require("data/observable");
import pages = require("ui/page"); import pages = require("ui/page");
import transition = require("ui/transition");
/** /**
* Represents the logical View unit that is responsible for navigation withing an application. * Represents the logical View unit that is responsible for navigation withing an application.
@ -77,7 +78,7 @@ declare module "ui/frame" {
/** /**
* Gets or sets the default navigation transition for this frame. * Gets or sets the default navigation transition for this frame.
*/ */
navigationTransition: NavigationTransition; transition: NavigationTransition;
/** /**
* Gets or sets if navigation transitions should be animated globally. * Gets or sets if navigation transitions should be animated globally.
@ -87,7 +88,7 @@ declare module "ui/frame" {
/** /**
* Gets or sets the default NavigationTransition for all frames across the app. * Gets or sets the default NavigationTransition for all frames across the app.
*/ */
static defaultNavigationTransition: NavigationTransition; static defaultTransition: NavigationTransition;
/** /**
* Gets the AndroidFrame object that represents the Android-specific APIs for this Frame. Valid when running on Android OS. * Gets the AndroidFrame object that represents the Android-specific APIs for this Frame. Valid when running on Android OS.
@ -161,9 +162,19 @@ declare module "ui/frame" {
animated?: boolean; animated?: boolean;
/** /**
* Specifies an optional navigation transition. If not specified, the default platform transition will be used. * Specifies an optional navigation transition for all platforms. If not specified, the default platform transition will be used.
*/ */
navigationTransition?: NavigationTransition; transition?: NavigationTransition;
/**
* Specifies an optional navigation transition for iOS. If not specified, the default platform transition will be used.
*/
transitioniOS?: NavigationTransition;
/**
* Specifies an optional navigation transition for iOS. If not specified, the default platform transition will be used.
*/
transitionAndroid?: NavigationTransition;
/** /**
* True to record the navigation in the backstack, false otherwise. * True to record the navigation in the backstack, false otherwise.
@ -182,9 +193,27 @@ declare module "ui/frame" {
*/ */
export interface NavigationTransition { export interface NavigationTransition {
/** /**
* Either a string specifying one of the built-in transitions or an user-defined instance of the "ui/transition".Transition class. * Can be one of the built-in transitions:
* - curl (same as curlUp) (iOS only)
* - curlUp (iOS only)
* - curlDown (iOS only)
* - explode (Android Lollipop an up only)
* - fade
* - flip (same as flipRight)
* - flipRight
* - flipLeft
* - slide (same as slideLeft)
* - slideLeft
* - slideRight
* - slideTop
* - slideBottom
*/ */
transition: any; name?: string;
/**
* An user-defined instance of the "ui/transition".Transition class.
*/
instance?: transition.Transition;
/** /**
* The length of the transition in milliseconds. If you do not specify this, the default platform transition duration will be used. * The length of the transition in milliseconds. If you do not specify this, the default platform transition duration will be used.

View File

@ -189,11 +189,11 @@ export class Frame extends frameCommon.Frame {
frameCommon.Frame.defaultAnimatedNavigation = value; frameCommon.Frame.defaultAnimatedNavigation = value;
} }
public static get defaultNavigationTransition(): definition.NavigationTransition { public static get defaultTransition(): definition.NavigationTransition {
return frameCommon.Frame.defaultNavigationTransition; return frameCommon.Frame.defaultTransition;
} }
public static set defaultNavigationTransition(value: definition.NavigationTransition) { public static set defaultTransition(value: definition.NavigationTransition) {
frameCommon.Frame.defaultNavigationTransition = value; frameCommon.Frame.defaultTransition = value;
} }
public requestLayout(): void { public requestLayout(): void {
@ -640,8 +640,8 @@ function _getTransitionId(nativeTransition: UIViewAnimationTransition, transitio
} }
function _getNativeTransition(navigationTransition: definition.NavigationTransition, push: boolean): UIViewAnimationTransition { function _getNativeTransition(navigationTransition: definition.NavigationTransition, push: boolean): UIViewAnimationTransition {
if (types.isString(navigationTransition.transition)) { if (navigationTransition.name) {
switch (navigationTransition.transition.toLowerCase()) { switch (navigationTransition.name.toLowerCase()) {
case "flip": case "flip":
case "flipright": case "flipright":
return push ? UIViewAnimationTransition.UIViewAnimationTransitionFlipFromRight : UIViewAnimationTransition.UIViewAnimationTransitionFlipFromLeft; return push ? UIViewAnimationTransition.UIViewAnimationTransitionFlipFromRight : UIViewAnimationTransition.UIViewAnimationTransitionFlipFromLeft;

View File

@ -47,8 +47,8 @@ export function _clearForwardTransitions(fragment: any): void {
export function _setAndroidFragmentTransitions(navigationTransition: frameModule.NavigationTransition, currentFragment: any, newFragment: any, fragmentTransaction: any): void { export function _setAndroidFragmentTransitions(navigationTransition: frameModule.NavigationTransition, currentFragment: any, newFragment: any, fragmentTransaction: any): void {
var name; var name;
if (types.isString(navigationTransition.transition)) { if (navigationTransition.name) {
name = navigationTransition.transition.toLowerCase(); name = navigationTransition.name.toLowerCase();
} }
var useLollipopTransition = name && (name.indexOf("slide") === 0 || name === "fade" || name === "explode") && _sdkVersion >= 21; var useLollipopTransition = name && (name.indexOf("slide") === 0 || name === "fade" || name === "explode") && _sdkVersion >= 21;
@ -153,7 +153,7 @@ export function _setAndroidFragmentTransitions(navigationTransition: frameModule
return; return;
} }
var transition: Transition; var transition: definition.Transition;
if (name) { if (name) {
if (name.indexOf("slide") === 0) { if (name.indexOf("slide") === 0) {
var slideTransitionModule = require("./slide-transition"); var slideTransitionModule = require("./slide-transition");
@ -171,7 +171,7 @@ export function _setAndroidFragmentTransitions(navigationTransition: frameModule
} }
} }
else { else {
transition = navigationTransition.transition; // User-defined instance of Transition transition = navigationTransition.instance; // User-defined instance of Transition
} }
if (transition) { if (transition) {

View File

@ -6,13 +6,13 @@ import trace = require("trace");
class AnimatedTransitioning extends NSObject implements UIViewControllerAnimatedTransitioning { class AnimatedTransitioning extends NSObject implements UIViewControllerAnimatedTransitioning {
public static ObjCProtocols = [UIViewControllerAnimatedTransitioning]; public static ObjCProtocols = [UIViewControllerAnimatedTransitioning];
private _transition: Transition; private _transition: definition.Transition;
private _operation: UINavigationControllerOperation; private _operation: UINavigationControllerOperation;
private _fromVC: UIViewController; private _fromVC: UIViewController;
private _toVC: UIViewController; private _toVC: UIViewController;
private _transitionType: string; private _transitionType: string;
public static init(transition: Transition, operation: UINavigationControllerOperation, fromVC: UIViewController, toVC: UIViewController): AnimatedTransitioning { public static init(transition: definition.Transition, operation: UINavigationControllerOperation, fromVC: UIViewController, toVC: UIViewController): AnimatedTransitioning {
var impl = <AnimatedTransitioning>AnimatedTransitioning.new(); var impl = <AnimatedTransitioning>AnimatedTransitioning.new();
impl._transition = transition; impl._transition = transition;
impl._operation = operation; impl._operation = operation;
@ -31,6 +31,7 @@ class AnimatedTransitioning extends NSObject implements UIViewControllerAnimated
case UINavigationControllerOperation.UINavigationControllerOperationPop: this._transitionType = "pop"; break; case UINavigationControllerOperation.UINavigationControllerOperationPop: this._transitionType = "pop"; break;
case UINavigationControllerOperation.UINavigationControllerOperationNone: this._transitionType = "none"; break; case UINavigationControllerOperation.UINavigationControllerOperationNone: this._transitionType = "none"; break;
} }
trace.write(`START ${this._transition} ${this._transitionType}`, trace.categories.Transition); trace.write(`START ${this._transition} ${this._transitionType}`, trace.categories.Transition);
this._transition.animateIOSTransition(containerView, this._fromVC.view, this._toVC.view, this._operation, completion); this._transition.animateIOSTransition(containerView, this._fromVC.view, this._toVC.view, this._operation, completion);
} }
@ -87,10 +88,10 @@ export class Transition implements definition.Transition {
} }
export function _createIOSAnimatedTransitioning(navigationTransition: frame.NavigationTransition, operation: UINavigationControllerOperation, fromVC: UIViewController, toVC: UIViewController): UIViewControllerAnimatedTransitioning { export function _createIOSAnimatedTransitioning(navigationTransition: frame.NavigationTransition, operation: UINavigationControllerOperation, fromVC: UIViewController, toVC: UIViewController): UIViewControllerAnimatedTransitioning {
var transition: Transition; var transition: definition.Transition;
if (types.isString(navigationTransition.transition)) { if (navigationTransition.name) {
var name = navigationTransition.transition.toLowerCase(); var name = navigationTransition.name.toLowerCase();
if (name.indexOf("slide") === 0) { if (name.indexOf("slide") === 0) {
var slideTransitionModule = require("./slide-transition"); var slideTransitionModule = require("./slide-transition");
var direction = name.substr("slide".length) || "left"; //Extract the direction from the string var direction = name.substr("slide".length) || "left"; //Extract the direction from the string
@ -102,7 +103,7 @@ export function _createIOSAnimatedTransitioning(navigationTransition: frame.Navi
} }
} }
else { else {
transition = navigationTransition.transition; transition = navigationTransition.instance;
} }
if (transition) { if (transition) {