Merge pull request #788 from NativeScript/issue-759

Fixed: Android animations that animate a property to its current valu…
This commit is contained in:
Rossen Hristov
2015-09-21 11:03:00 +03:00
2 changed files with 230 additions and 211 deletions

View File

@ -44,62 +44,62 @@ export var test_AnimatingProperties = function (done) {
curve: label.ios ? UIViewAnimationCurve.UIViewAnimationCurveEaseIn : new android.view.animation.AccelerateInterpolator(1), curve: label.ios ? UIViewAnimationCurve.UIViewAnimationCurveEaseIn : new android.view.animation.AccelerateInterpolator(1),
}) })
.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_CancellingAnimation = function (done) { export var test_CancellingAnimation = 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">
// # 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().finished
.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("Animation cancelled"); ////console.log("Animation cancelled");
// <hide> // <hide>
helper.goBack(); helper.goBack();
done(); done();
// </hide> // </hide>
}); });
animation1.cancel(); animation1.cancel();
// ``` // ```
// </snippet> // </snippet>
} }
export var test_ChainingAnimations = function (done) { export var test_ChainingAnimations = function (done) {
var mainPage: pageModule.Page; var mainPage: pageModule.Page;
@ -128,119 +128,119 @@ export var test_ChainingAnimations = function (done) {
.then(() => label.animate({ rotate: 180 })) .then(() => label.animate({ rotate: 180 }))
.then(() => label.animate({ rotate: 0 })) .then(() => label.animate({ rotate: 0 }))
.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_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().finished
.then(() => animation1.play().finished) // .then(() => animation1.play().finished)
.then(() => animation1.play().finished) // .then(() => animation1.play().finished)
.then(() => animation2.play().finished) // .then(() => animation2.play().finished)
.then(() => animation1.play().finished) // .then(() => animation1.play().finished)
.then(() => animation2.play().finished) // .then(() => animation2.play().finished)
.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;
var label1: labelModule.Label; var label1: labelModule.Label;
var label2: labelModule.Label; var label2: labelModule.Label;
var label3: labelModule.Label; var label3: labelModule.Label;
var pageFactory = function (): pageModule.Page { var pageFactory = function (): pageModule.Page {
label1 = new labelModule.Label(); label1 = new labelModule.Label();
label1.text = "label1"; label1.text = "label1";
label2 = new labelModule.Label(); label2 = new labelModule.Label();
label2.text = "label2"; label2.text = "label2";
label3 = new labelModule.Label(); label3 = new labelModule.Label();
label3.text = "label3"; label3.text = "label3";
var stackLayout = new stackLayoutModule.StackLayout(); var stackLayout = new stackLayoutModule.StackLayout();
stackLayout.addChild(label1); stackLayout.addChild(label1);
stackLayout.addChild(label2); stackLayout.addChild(label2);
stackLayout.addChild(label3); stackLayout.addChild(label3);
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 label1.isLoaded && label2.isLoaded }); TKUnit.waitUntilReady(() => { return label1.isLoaded && label2.isLoaded });
// <snippet module="ui/animation" title="animation"> // <snippet module="ui/animation" title="animation">
// # Animating multiple views simultaneously // # Animating multiple views simultaneously
// ``` JavaScript // ``` JavaScript
var animations: Array<animation.AnimationDefinition> = [ var animations: Array<animation.AnimationDefinition> = [
{ target: label1, translate: { x: 200, y: 200 }, duration: 1000, delay: 0 }, { target: label1, translate: { x: 200, y: 200 }, duration: 1000, delay: 0 },
{ target: label2, translate: { x: 200, y: 200 }, duration: 1000, delay: 333 }, { target: label2, translate: { x: 200, y: 200 }, duration: 1000, delay: 333 },
{ 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().finished
.then(() => { .then(() => {
////console.log("Animations finished"); ////console.log("Animations 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_AnimateOpacity = function (done) { export var test_AnimateOpacity = function (done) {
var mainPage: pageModule.Page; var mainPage: pageModule.Page;
@ -258,7 +258,7 @@ export var test_AnimateOpacity = function (done) {
helper.navigate(pageFactory); helper.navigate(pageFactory);
TKUnit.waitUntilReady(() => { return label.isLoaded }); TKUnit.waitUntilReady(() => { return label.isLoaded });
label.animate({opacity: 0.75}) label.animate({ opacity: 0.75 })
.then(() => { .then(() => {
TKUnit.assert(label.opacity === 0.75); TKUnit.assert(label.opacity === 0.75);
helper.goBack(); helper.goBack();
@ -289,7 +289,7 @@ export var test_AnimateBackgroundColor = function (done) {
label.animate({ backgroundColor: red }) label.animate({ backgroundColor: red })
.then(() => { .then(() => {
TKUnit.assert(label.backgroundColor.equals(red)); TKUnit.assert(label.backgroundColor.equals(red));
helper.goBack(); helper.goBack();
done(); done();
}) })
@ -315,7 +315,7 @@ export var test_AnimateTranslate = function (done) {
helper.navigate(pageFactory); helper.navigate(pageFactory);
TKUnit.waitUntilReady(() => { return label.isLoaded }); TKUnit.waitUntilReady(() => { return label.isLoaded });
label.animate({ translate: {x: 100, y: 200} }) label.animate({ translate: { x: 100, y: 200 } })
.then(() => { .then(() => {
TKUnit.assert(label.translateX === 100); TKUnit.assert(label.translateX === 100);
TKUnit.assert(label.translateY === 200); TKUnit.assert(label.translateY === 200);
@ -384,3 +384,36 @@ export var test_AnimateRotate = function (done) {
done(e); done(e);
}); });
} }
export var test_AnimationsAreAlwaysPlayed = 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 animation1 = label.createAnimation({ opacity: 0 });
var animation2 = label.createAnimation({ opacity: 1 });
animation1.play().finished
.then(() => animation2.play().finished)
.then(() => {
TKUnit.assert(label.opacity === 1, `Label opacity expected vaue is 1, actual value is ${label.opacity}.`);
helper.goBack();
done();
})
.catch((e) => {
console.log(e.message);
helper.goBack();
done(e);
});
}

View File

@ -148,84 +148,70 @@ export class Animation extends common.Animation implements definition.Animation
case common.Properties.opacity: case common.Properties.opacity:
originalValue = nativeView.getAlpha(); originalValue = nativeView.getAlpha();
if (propertyAnimation.value !== propertyAnimation.target.opacity) { nativeArray = java.lang.reflect.Array.newInstance(floatType, 1);
nativeArray = java.lang.reflect.Array.newInstance(floatType, 1); nativeArray[0] = propertyAnimation.value;
nativeArray[0] = propertyAnimation.value; animators.push(android.animation.ObjectAnimator.ofFloat(nativeView, "alpha", nativeArray));
animators.push(android.animation.ObjectAnimator.ofFloat(nativeView, "alpha", nativeArray)); propertyUpdateCallbacks.push(() => { propertyAnimation.target.opacity = propertyAnimation.value });
propertyUpdateCallbacks.push(() => { propertyAnimation.target.opacity = propertyAnimation.value }); propertyResetCallbacks.push(() => { nativeView.setAlpha(originalValue); });
propertyResetCallbacks.push(() => { nativeView.setAlpha(originalValue); });
}
break; break;
case common.Properties.backgroundColor: case common.Properties.backgroundColor:
originalValue = nativeView.getBackground(); originalValue = nativeView.getBackground();
if (!color.Color.equals(propertyAnimation.value, propertyAnimation.target.backgroundColor)) { nativeArray = java.lang.reflect.Array.newInstance(java.lang.Object.class, 2);
nativeArray = java.lang.reflect.Array.newInstance(java.lang.Object.class, 2); nativeArray[0] = propertyAnimation.target.backgroundColor ? java.lang.Integer.valueOf((<color.Color>propertyAnimation.target.backgroundColor).argb) : java.lang.Integer.valueOf(-1);
nativeArray[0] = propertyAnimation.target.backgroundColor ? java.lang.Integer.valueOf((<color.Color>propertyAnimation.target.backgroundColor).argb) : java.lang.Integer.valueOf(-1); nativeArray[1] = java.lang.Integer.valueOf((<color.Color>propertyAnimation.value).argb);
nativeArray[1] = java.lang.Integer.valueOf((<color.Color>propertyAnimation.value).argb); animator = android.animation.ValueAnimator.ofObject(argbEvaluator, nativeArray);
animator = android.animation.ValueAnimator.ofObject(argbEvaluator, nativeArray); animator.addUpdateListener(new android.animation.ValueAnimator.AnimatorUpdateListener({
animator.addUpdateListener(new android.animation.ValueAnimator.AnimatorUpdateListener({ onAnimationUpdate(animator: android.animation.ValueAnimator) {
onAnimationUpdate(animator: android.animation.ValueAnimator) { var argb = (<java.lang.Integer>animator.getAnimatedValue()).intValue();
var argb = (<java.lang.Integer>animator.getAnimatedValue()).intValue(); propertyAnimation.target.backgroundColor = new color.Color(argb);
propertyAnimation.target.backgroundColor = new color.Color(argb); }
} }));
}));
animators.push(animator); animators.push(animator);
propertyUpdateCallbacks.push(() => { propertyAnimation.target.backgroundColor = propertyAnimation.value; }); propertyUpdateCallbacks.push(() => { propertyAnimation.target.backgroundColor = propertyAnimation.value; });
propertyResetCallbacks.push(() => { nativeView.setBackground(originalValue); }); propertyResetCallbacks.push(() => { nativeView.setBackground(originalValue); });
}
break; break;
case common.Properties.translate: case common.Properties.translate:
originalValue = nativeView.getTranslationX(); originalValue = nativeView.getTranslationX();
if (propertyAnimation.value.x * density !== originalValue) { nativeArray = java.lang.reflect.Array.newInstance(floatType, 1);
nativeArray = java.lang.reflect.Array.newInstance(floatType, 1); nativeArray[0] = propertyAnimation.value.x * density;
nativeArray[0] = propertyAnimation.value.x * density; animators.push(android.animation.ObjectAnimator.ofFloat(nativeView, "translationX", nativeArray));
animators.push(android.animation.ObjectAnimator.ofFloat(nativeView, "translationX", nativeArray)); propertyUpdateCallbacks.push(() => { propertyAnimation.target.translateX = propertyAnimation.value.x; });
propertyUpdateCallbacks.push(() => { propertyAnimation.target.translateX = propertyAnimation.value.x; }); propertyResetCallbacks.push(() => { nativeView.setTranslationX(originalValue); });
propertyResetCallbacks.push(() => { nativeView.setTranslationX(originalValue); });
}
originalValue = nativeView.getTranslationY(); originalValue = nativeView.getTranslationY();
if (propertyAnimation.value.y * density !== originalValue) { nativeArray = java.lang.reflect.Array.newInstance(floatType, 1);
nativeArray = java.lang.reflect.Array.newInstance(floatType, 1); nativeArray[0] = propertyAnimation.value.y * density;
nativeArray[0] = propertyAnimation.value.y * density; animators.push(android.animation.ObjectAnimator.ofFloat(nativeView, "translationY", nativeArray));
animators.push(android.animation.ObjectAnimator.ofFloat(nativeView, "translationY", nativeArray)); propertyUpdateCallbacks.push(() => { propertyAnimation.target.translateY = propertyAnimation.value.y; });
propertyUpdateCallbacks.push(() => { propertyAnimation.target.translateY = propertyAnimation.value.y; }); propertyResetCallbacks.push(() => { nativeView.setTranslationY(originalValue); });
propertyResetCallbacks.push(() => { nativeView.setTranslationY(originalValue); });
}
break; break;
case common.Properties.rotate: case common.Properties.rotate:
originalValue = nativeView.getRotation(); originalValue = nativeView.getRotation();
if (propertyAnimation.value !== originalValue) { nativeArray = java.lang.reflect.Array.newInstance(floatType, 1);
nativeArray = java.lang.reflect.Array.newInstance(floatType, 1); nativeArray[0] = propertyAnimation.value;
nativeArray[0] = propertyAnimation.value; animators.push(android.animation.ObjectAnimator.ofFloat(nativeView, "rotation", nativeArray));
animators.push(android.animation.ObjectAnimator.ofFloat(nativeView, "rotation", nativeArray)); propertyUpdateCallbacks.push(() => { propertyAnimation.target.rotate = propertyAnimation.value; });
propertyUpdateCallbacks.push(() => { propertyAnimation.target.rotate = propertyAnimation.value; }); propertyResetCallbacks.push(() => { nativeView.setRotation(originalValue); });
propertyResetCallbacks.push(() => { nativeView.setRotation(originalValue); });
}
break; break;
case common.Properties.scale: case common.Properties.scale:
originalValue = nativeView.getScaleX(); originalValue = nativeView.getScaleX();
if (propertyAnimation.value.x !== originalValue) { nativeArray = java.lang.reflect.Array.newInstance(floatType, 1);
nativeArray = java.lang.reflect.Array.newInstance(floatType, 1); nativeArray[0] = propertyAnimation.value.x;
nativeArray[0] = propertyAnimation.value.x; animators.push(android.animation.ObjectAnimator.ofFloat(nativeView, "scaleX", nativeArray));
animators.push(android.animation.ObjectAnimator.ofFloat(nativeView, "scaleX", nativeArray)); propertyUpdateCallbacks.push(() => { propertyAnimation.target.scaleX = propertyAnimation.value.x; });
propertyUpdateCallbacks.push(() => { propertyAnimation.target.scaleX = propertyAnimation.value.x; }); propertyResetCallbacks.push(() => { nativeView.setScaleX(originalValue); });
propertyResetCallbacks.push(() => { nativeView.setScaleX(originalValue); });
}
originalValue = nativeView.getScaleY(); originalValue = nativeView.getScaleY();
if (propertyAnimation.value.y !== originalValue) { nativeArray = java.lang.reflect.Array.newInstance(floatType, 1);
nativeArray = java.lang.reflect.Array.newInstance(floatType, 1); nativeArray[0] = propertyAnimation.value.y;
nativeArray[0] = propertyAnimation.value.y; animators.push(android.animation.ObjectAnimator.ofFloat(nativeView, "scaleY", nativeArray));
animators.push(android.animation.ObjectAnimator.ofFloat(nativeView, "scaleY", nativeArray)); propertyUpdateCallbacks.push(() => { propertyAnimation.target.scaleY = propertyAnimation.value.y; });
propertyUpdateCallbacks.push(() => { propertyAnimation.target.scaleY = propertyAnimation.value.y; }); propertyResetCallbacks.push(() => { nativeView.setScaleY(originalValue); });
propertyResetCallbacks.push(() => { nativeView.setScaleY(originalValue); });
}
break; break;
default: default: