Merge pull request #791 from NativeScript/hristov/issue-774

Fixed: If an Animation instance is played more than once, the same pr…
This commit is contained in:
Rossen Hristov
2015-09-21 13:46:56 +03:00
7 changed files with 132 additions and 79 deletions

View File

@ -38,8 +38,8 @@ export function onSlideOut(args: observable.EventData) {
panelAnimation = panel.createAnimation({ opacity: 0, scale: { x: 0.5, y: 0.5 }, rotate: -360, backgroundColor: new colorModule.Color("red"), duration: vm.duration, iterations: vm.iterations }); panelAnimation = panel.createAnimation({ opacity: 0, scale: { x: 0.5, y: 0.5 }, rotate: -360, backgroundColor: new colorModule.Color("red"), duration: vm.duration, iterations: vm.iterations });
buttonAnimation.play().finished buttonAnimation.play()
.then(() => panelAnimation.play().finished) .then(() => panelAnimation.play())
.catch((e) => console.log(e.message)); .catch((e) => console.log(e.message));
} }
@ -56,8 +56,8 @@ export function onSlideIn(args: observable.EventData) {
] ]
buttonAnimation = new animationModule.Animation(buttonAnimations, vm.playSequentially); buttonAnimation = new animationModule.Animation(buttonAnimations, vm.playSequentially);
panelAnimation.play().finished panelAnimation.play()
.then(() => buttonAnimation.play().finished) .then(() => buttonAnimation.play())
.catch((e) => console.log(e.message)); .catch((e) => console.log(e.message));
} }

View File

@ -81,7 +81,7 @@ export var test_CancellingAnimation = function (done) {
// # Cancelling animation // # Cancelling animation
// ``` JavaScript // ``` JavaScript
var animation1 = label.createAnimation({ translate: { x: 100, y: 100 } }); var animation1 = label.createAnimation({ translate: { x: 100, y: 100 } });
animation1.play().finished animation1.play()
.then(() => { .then(() => {
////console.log("Animation finished"); ////console.log("Animation finished");
// <hide> // <hide>
@ -145,51 +145,51 @@ export var test_ChainingAnimations = function (done) {
// </snippet> // </snippet>
} }
//export var test_ReusingAnimations = function (done) { export var test_ReusingAnimations = function (done) {
// var mainPage: pageModule.Page; var mainPage: pageModule.Page;
// var label: labelModule.Label; var label: labelModule.Label;
// var pageFactory = function (): pageModule.Page { var pageFactory = function (): pageModule.Page {
// label = new labelModule.Label(); label = new labelModule.Label();
// label.text = "label"; label.text = "label";
// var stackLayout = new stackLayoutModule.StackLayout(); var stackLayout = new stackLayoutModule.StackLayout();
// stackLayout.addChild(label); stackLayout.addChild(label);
// mainPage = new pageModule.Page(); mainPage = new pageModule.Page();
// mainPage.content = stackLayout; mainPage.content = stackLayout;
// return mainPage; return mainPage;
// }; };
// helper.navigate(pageFactory); helper.navigate(pageFactory);
// TKUnit.waitUntilReady(() => { return label.isLoaded }); TKUnit.waitUntilReady(() => { return label.isLoaded });
// // <snippet module="ui/animation" title="animation"> // <snippet module="ui/animation" title="animation">
// // # Reusing animations // # Reusing animations
// // ``` JavaScript // ``` JavaScript
// var animation1 = label.createAnimation({ translate: { x: 100, y: 100 } }); var animation1 = label.createAnimation({ translate: { x: 100, y: 100 } });
// var animation2 = label.createAnimation({ translate: { x: 0, y: 0 } }); var animation2 = label.createAnimation({ translate: { x: 0, y: 0 } });
// animation1.play().finished animation1.play()
// .then(() => animation1.play().finished) .then(() => animation2.play())
// .then(() => animation1.play().finished) .then(() => animation1.play())
// .then(() => animation2.play().finished) .then(() => animation2.play())
// .then(() => animation1.play().finished) .then(() => animation1.play())
// .then(() => animation2.play().finished) .then(() => animation2.play())
// .then(() => { .then(() => {
// ////console.log("Animation finished"); ////console.log("Animation finished");
// // <hide> // <hide>
// helper.goBack(); helper.goBack();
// done(); done();
// // </hide> // </hide>
// }) })
// .catch((e) => { .catch((e) => {
// console.log(e.message); console.log(e.message);
// // <hide> // <hide>
// helper.goBack(); helper.goBack();
// done(e); done(e);
// // </hide> // </hide>
// }); });
// // ``` // ```
// // </snippet> // </snippet>
//} }
export var test_AnimatingMultipleViews = function (done) { export var test_AnimatingMultipleViews = function (done) {
var mainPage: pageModule.Page; var mainPage: pageModule.Page;
@ -223,7 +223,7 @@ export var test_AnimatingMultipleViews = function (done) {
{ target: label3, translate: { x: 200, y: 200 }, duration: 1000, delay: 666 }, { target: label3, translate: { x: 200, y: 200 }, duration: 1000, delay: 666 },
]; ];
var a = new animation.Animation(animations); var a = new animation.Animation(animations);
a.play().finished a.play()
.then(() => { .then(() => {
////console.log("Animations finished"); ////console.log("Animations finished");
// <hide> // <hide>
@ -404,10 +404,13 @@ export var test_AnimationsAreAlwaysPlayed = function (done) {
var animation1 = label.createAnimation({ opacity: 0 }); var animation1 = label.createAnimation({ opacity: 0 });
var animation2 = label.createAnimation({ opacity: 1 }); var animation2 = label.createAnimation({ opacity: 1 });
animation1.play().finished animation1.play()
.then(() => animation2.play().finished)
.then(() => { .then(() => {
TKUnit.assert(label.opacity === 1, `Label opacity expected vaue is 1, actual value is ${label.opacity}.`); TKUnit.assert(label.opacity === 0, `Label opacity should be 0 after first animation, actual value is ${label.opacity}.`);
return animation2.play()
})
.then(() => {
TKUnit.assert(label.opacity === 1, `Label opacity should be 1 after second animation, actual value is ${label.opacity}.`);
helper.goBack(); helper.goBack();
done(); done();
}) })
@ -417,3 +420,65 @@ export var test_AnimationsAreAlwaysPlayed = function (done) {
done(e); done(e);
}); });
} }
export var test_PlayPromiseIsResolvedWhenAnimationFinishes = function (done) {
var mainPage: pageModule.Page;
var label: labelModule.Label;
var pageFactory = function (): pageModule.Page {
label = new labelModule.Label();
label.text = "label";
var stackLayout = new stackLayoutModule.StackLayout();
stackLayout.addChild(label);
mainPage = new pageModule.Page();
mainPage.content = stackLayout;
return mainPage;
};
helper.navigate(pageFactory);
TKUnit.waitUntilReady(() => { return label.isLoaded });
var animation = label.createAnimation({ opacity: 0, duration: 1000 });
animation.play()
.then(function onResolved() {
TKUnit.assert(animation.isPlaying === false, "Animation.isPlaying should be false when animation play promise is resolved.");
helper.goBack();
done();
}, function onRejected(e) {
TKUnit.assert(1 === 2, "Animation play promise should be resolved, not rejected.");
helper.goBack();
done(e);
});
}
export var test_PlayPromiseIsRejectedWhenAnimationIsCancelled = function (done) {
var mainPage: pageModule.Page;
var label: labelModule.Label;
var pageFactory = function (): pageModule.Page {
label = new labelModule.Label();
label.text = "label";
var stackLayout = new stackLayoutModule.StackLayout();
stackLayout.addChild(label);
mainPage = new pageModule.Page();
mainPage.content = stackLayout;
return mainPage;
};
helper.navigate(pageFactory);
TKUnit.waitUntilReady(() => { return label.isLoaded });
var animation = label.createAnimation({ opacity: 0, duration: 1000 });
animation.play()
.then(function onResolved() {
TKUnit.assert(1 === 2, "Animation play promise should be rejected, not resolved.");
helper.goBack();
done();
}, function onRejected(e) {
TKUnit.assert(animation.isPlaying === false, "Animation.isPlaying should be false when animation play promise is rejected.");
helper.goBack();
done();
});
animation.cancel();
}

View File

@ -26,15 +26,19 @@ export class Animation implements definition.Animation {
private _isPlaying: boolean; private _isPlaying: boolean;
private _resolve; private _resolve;
private _reject; private _reject;
private _animationFinishedPromise: Promise<void>;
public play(): Animation { public play(): Promise<void> {
if (this.isPlaying) { if (this.isPlaying) {
throw new Error("Animation is already playing."); throw new Error("Animation is already playing.");
} }
var animationFinishedPromise = new Promise<void>((resolve, reject) => {
this._resolve = resolve;
this._reject = reject;
});
this._isPlaying = true; this._isPlaying = true;
return this; return animationFinishedPromise;
} }
public cancel(): void { public cancel(): void {
@ -43,10 +47,6 @@ export class Animation implements definition.Animation {
} }
} }
public get finished(): Promise<void> {
return this._animationFinishedPromise;
}
public get isPlaying(): boolean { public get isPlaying(): boolean {
return this._isPlaying; return this._isPlaying;
} }
@ -70,11 +70,6 @@ export class Animation implements definition.Animation {
trace.write("Created " + this._propertyAnimations.length + " individual property animations.", trace.categories.Animation); trace.write("Created " + this._propertyAnimations.length + " individual property animations.", trace.categories.Animation);
this._playSequentially = playSequentially; this._playSequentially = playSequentially;
var that = this;
this._animationFinishedPromise = new Promise<void>((resolve, reject) => {
that._resolve = resolve;
that._reject = reject;
});
} }
public _resolveAnimationFinishedPromise() { public _resolveAnimationFinishedPromise() {

View File

@ -18,8 +18,8 @@ export class Animation extends common.Animation implements definition.Animation
private _propertyUpdateCallbacks: Array<Function>; private _propertyUpdateCallbacks: Array<Function>;
private _propertyResetCallbacks: Array<Function>; private _propertyResetCallbacks: Array<Function>;
public play(): Animation { public play(): Promise<void> {
super.play(); var animationFinishedPromise = super.play();
var i: number; var i: number;
var length: number; var length: number;
@ -34,12 +34,6 @@ export class Animation extends common.Animation implements definition.Animation
this._createAnimators(this._propertyAnimations[i]); this._createAnimators(this._propertyAnimations[i]);
} }
if (this._animators.length === 0) {
trace.write("Nothing to animate.", trace.categories.Animation);
this._resolveAnimationFinishedPromise();
return this;
}
this._nativeAnimatorsArray = java.lang.reflect.Array.newInstance(android.animation.Animator.class, this._animators.length); this._nativeAnimatorsArray = java.lang.reflect.Array.newInstance(android.animation.Animator.class, this._animators.length);
i = 0; i = 0;
length = this._animators.length; length = this._animators.length;
@ -58,7 +52,7 @@ export class Animation extends common.Animation implements definition.Animation
trace.write("Starting " + this._nativeAnimatorsArray.length + " animations " + (this._playSequentially ? "sequentially." : "together."), trace.categories.Animation); trace.write("Starting " + this._nativeAnimatorsArray.length + " animations " + (this._playSequentially ? "sequentially." : "together."), trace.categories.Animation);
this._animatorSet.start(); this._animatorSet.start();
return this; return animationFinishedPromise;
} }
public cancel(): void { public cancel(): void {

View File

@ -72,9 +72,8 @@
*/ */
export class Animation { export class Animation {
constructor(animationDefinitions: Array<AnimationDefinition>, playSequentially?: boolean); constructor(animationDefinitions: Array<AnimationDefinition>, playSequentially?: boolean);
public play: () => Animation; public play: () => Promise<void>;
public cancel: () => void; public cancel: () => void;
public finished: Promise<void>;
public isPlaying: boolean; public isPlaying: boolean;
} }
} }

View File

@ -46,14 +46,14 @@ export class Animation extends common.Animation implements definition.Animation
private _cancelledAnimations: number; private _cancelledAnimations: number;
private _mergedPropertyAnimations: Array<common.PropertyAnimation>; private _mergedPropertyAnimations: Array<common.PropertyAnimation>;
public play(): Animation { public play(): Promise<void> {
super.play(); var animationFinishedPromise = super.play();
this._finishedAnimations = 0; this._finishedAnimations = 0;
this._cancelledAnimations = 0; this._cancelledAnimations = 0;
this._iOSAnimationFunction();
return this; this._iOSAnimationFunction();
return animationFinishedPromise;
} }
public cancel(): void { public cancel(): void {

View File

@ -1099,7 +1099,7 @@ export class View extends proxy.ProxyObject implements definition.View {
} }
public animate(animation: animationModule.AnimationDefinition): Promise<void> { public animate(animation: animationModule.AnimationDefinition): Promise<void> {
return this.createAnimation(animation).play().finished; return this.createAnimation(animation).play();
} }
public createAnimation(animation: animationModule.AnimationDefinition): animationModule.Animation { public createAnimation(animation: animationModule.AnimationDefinition): animationModule.Animation {