Merge pull request #1165 from NativeScript/feature/animation-fixes

Feature/animation fixes
This commit is contained in:
Alexander Vakrilov
2015-11-27 16:13:14 +02:00
4 changed files with 121 additions and 131 deletions

View File

@@ -83,9 +83,9 @@ allTests["REPEATER"] = require("./ui/repeater/repeater-tests");
allTests["SEARCH-BAR"] = require('./ui/search-bar/search-bar-tests');
allTests["CONNECTIVITY"] = require("./connectivity-tests");
allTests["SEGMENTED-BAR"] = require("./ui/segmented-bar/segmented-bar-tests");
allTests["ANIMATION"] = require("./ui/animation/animation-tests");
if (!isRunningOnEmulator()) {
allTests["ANIMATION"] = require("./ui/animation/animation-tests");
allTests["LOCATION"] = require("./location-tests");
}
@@ -140,7 +140,7 @@ function startLog(): void {
function log(): void {
let testsName: string = this.name;
let duration = TKUnit.time() - this.start;
TKUnit.write(testsName + " COMPLETED for " + duration, messageType.info);
TKUnit.write(testsName + " COMPLETED for " + duration + " BACKSTACK DEPTH: " + topmost().backStack.length, messageType.info);
}
export var runAll = function (moduleName?: string) {
@@ -161,7 +161,7 @@ export var runAll = function (moduleName?: string) {
var test = testModule.createTestCase ? testModule.createTestCase() : testModule;
test.name = name;
testsQueue.push(new TestInfo(startLog, test));

View File

@@ -269,7 +269,7 @@ export var test_AnimateOpacity = function (done) {
label.animate({ opacity: 0.75 })
.then(() => {
TKUnit.assert(label.opacity === 0.75);
TKUnit.assertEqual(label.opacity, 0.75, "label.opacity");
helper.goBack();
done();
})
@@ -326,8 +326,8 @@ export var test_AnimateTranslate = function (done) {
label.animate({ translate: { x: 100, y: 200 } })
.then(() => {
TKUnit.assert(label.translateX === 100);
TKUnit.assert(label.translateY === 200);
TKUnit.assertEqual(label.translateX, 100, "label.translateX");
TKUnit.assertEqual(label.translateY, 200, "label.translateY");
assertIOSNativeTransformIsCorrect(label);
helper.goBack();
done();
@@ -356,8 +356,8 @@ export var test_AnimateScale = function (done) {
label.animate({ scale: { x: 2, y: 3 } })
.then(() => {
TKUnit.assert(label.scaleX === 2);
TKUnit.assert(label.scaleY === 3);
TKUnit.assertEqual(label.scaleX, 2,"label.scaleX");
TKUnit.assertEqual(label.scaleY, 3,"label.scaleY");
assertIOSNativeTransformIsCorrect(label);
helper.goBack();
done();
@@ -386,7 +386,7 @@ export var test_AnimateRotate = function (done) {
label.animate({ rotate: 123 })
.then(() => {
TKUnit.assert(label.rotate === 123);
TKUnit.assertEqual(label.rotate, 123, "label.rotate");
assertIOSNativeTransformIsCorrect(label);
helper.goBack();
done();
@@ -419,11 +419,11 @@ export var test_AnimateTranslateScaleAndRotateSimultaneously = function (done) {
rotate: 123
})
.then(() => {
TKUnit.assert(label.translateX === 100);
TKUnit.assert(label.translateY === 200);
TKUnit.assert(label.scaleX === 2);
TKUnit.assert(label.scaleY === 3);
TKUnit.assert(label.rotate === 123);
TKUnit.assertEqual(label.translateX, 100, "label.translateX");
TKUnit.assertEqual(label.translateY, 200, "label.translateY");
TKUnit.assertEqual(label.scaleX, 2, "label.scaleX");
TKUnit.assertEqual(label.scaleY, 3, "label.scaleY");
TKUnit.assertEqual(label.rotate, 123, "label.rotate");
assertIOSNativeTransformIsCorrect(label);
helper.goBack();
done();
@@ -450,35 +450,35 @@ export var test_AnimateTranslateScaleAndRotateSequentially = function (done) {
helper.navigate(pageFactory);
TKUnit.waitUntilReady(() => { return label.isLoaded });
label.animate({translate: { x: 100, y: 200 }})
.then(() => {
TKUnit.assert(label.translateX === 100);
TKUnit.assert(label.translateY === 200);
assertIOSNativeTransformIsCorrect(label);
return label.animate({ scale: { x: 2, y: 3 } });
})
.then(() => {
TKUnit.assert(label.translateX === 100);
TKUnit.assert(label.translateY === 200);
TKUnit.assert(label.scaleX === 2);
TKUnit.assert(label.scaleY === 3);
assertIOSNativeTransformIsCorrect(label);
return label.animate({ rotate: 123 });
})
.then(() => {
TKUnit.assert(label.translateX === 100);
TKUnit.assert(label.translateY === 200);
TKUnit.assert(label.scaleX === 2);
TKUnit.assert(label.scaleY === 3);
TKUnit.assert(label.rotate === 123);
assertIOSNativeTransformIsCorrect(label);
helper.goBack();
done();
})
.catch((e) => {
helper.goBack();
done(e);
});
label.animate({ translate: { x: 100, y: 200 } })
.then(() => {
TKUnit.assertEqual(label.translateX, 100, "label.translateX");
TKUnit.assertEqual(label.translateY, 200, "label.translateY");
assertIOSNativeTransformIsCorrect(label);
return label.animate({ scale: { x: 2, y: 3 } });
})
.then(() => {
TKUnit.assertEqual(label.translateX, 100, "label.translateX");
TKUnit.assertEqual(label.translateY, 200, "label.translateY");
TKUnit.assertEqual(label.scaleX, 2, "label.scaleX");
TKUnit.assertEqual(label.scaleY, 3, "label.scaleY");
assertIOSNativeTransformIsCorrect(label);
return label.animate({ rotate: 123 });
})
.then(() => {
TKUnit.assertEqual(label.translateX, 100, "label.translateX");
TKUnit.assertEqual(label.translateY, 200, "label.translateY");
TKUnit.assertEqual(label.scaleX, 2, "label.scaleX");
TKUnit.assertEqual(label.scaleY, 3, "label.scaleY");
TKUnit.assertEqual(label.rotate, 123, "label.rotate");
assertIOSNativeTransformIsCorrect(label);
helper.goBack();
done();
})
.catch((e) => {
helper.goBack();
done(e);
});
}
export var test_AnimationsAreAlwaysPlayed = function (done) {

View File

@@ -136,7 +136,8 @@ export class Animation extends common.Animation implements definition.Animation
var animators = new Array<android.animation.Animator>();
var propertyUpdateCallbacks = new Array<Function>();
var propertyResetCallbacks = new Array<Function>();
var originalValue;
var originalValue1;
var originalValue2;
var density = utils.layout.getDisplayDensity();
var xyObjectAnimators: any;
var animatorSet: android.animation.AnimatorSet;
@@ -157,16 +158,16 @@ export class Animation extends common.Animation implements definition.Animation
switch (propertyAnimation.property) {
case common.Properties.opacity:
originalValue = nativeView.getAlpha();
originalValue1 = nativeView.getAlpha();
nativeArray = java.lang.reflect.Array.newInstance(floatType, 1);
nativeArray[0] = propertyAnimation.value;
propertyUpdateCallbacks.push(checkAnimation(() => { propertyAnimation.target.opacity = propertyAnimation.value }));
propertyResetCallbacks.push(checkAnimation(() => { nativeView.setAlpha(originalValue); }));
propertyResetCallbacks.push(checkAnimation(() => { nativeView.setAlpha(originalValue1); }));
animators.push(android.animation.ObjectAnimator.ofFloat(nativeView, "alpha", nativeArray));
break;
case common.Properties.backgroundColor:
originalValue = nativeView.getBackground();
originalValue1 = nativeView.getBackground();
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[1] = java.lang.Integer.valueOf((<color.Color>propertyAnimation.value).argb);
@@ -179,28 +180,35 @@ export class Animation extends common.Animation implements definition.Animation
}));
propertyUpdateCallbacks.push(checkAnimation(() => { propertyAnimation.target.backgroundColor = propertyAnimation.value; }));
propertyResetCallbacks.push(checkAnimation(() => { nativeView.setBackground(originalValue); }));
propertyResetCallbacks.push(checkAnimation(() => { nativeView.setBackground(originalValue1); }));
animators.push(animator);
break;
case common.Properties.translate:
xyObjectAnimators = java.lang.reflect.Array.newInstance(android.animation.Animator.class, 2);
originalValue = nativeView.getTranslationX();
nativeArray = java.lang.reflect.Array.newInstance(floatType, 1);
nativeArray[0] = propertyAnimation.value.x * density;
xyObjectAnimators[0] = android.animation.ObjectAnimator.ofFloat(nativeView, "translationX", nativeArray);
xyObjectAnimators[0].setRepeatCount(Animation._getAndroidRepeatCount(propertyAnimation.iterations));
propertyUpdateCallbacks.push(checkAnimation(() => { propertyAnimation.target.translateX = propertyAnimation.value.x; }));
propertyResetCallbacks.push(checkAnimation(() => { nativeView.setTranslationX(originalValue); }));
originalValue = nativeView.getTranslationY();
nativeArray = java.lang.reflect.Array.newInstance(floatType, 1);
nativeArray[0] = propertyAnimation.value.y * density;
xyObjectAnimators[1] = android.animation.ObjectAnimator.ofFloat(nativeView, "translationY", nativeArray);
xyObjectAnimators[1].setRepeatCount(Animation._getAndroidRepeatCount(propertyAnimation.iterations));
propertyUpdateCallbacks.push(checkAnimation(() => { propertyAnimation.target.translateY = propertyAnimation.value.y; }));
propertyResetCallbacks.push(checkAnimation(() => { nativeView.setTranslationY(originalValue); }));
originalValue1 = nativeView.getTranslationX();
originalValue2 = nativeView.getTranslationY();
propertyUpdateCallbacks.push(checkAnimation(() => {
propertyAnimation.target.translateX = propertyAnimation.value.x;
propertyAnimation.target.translateY = propertyAnimation.value.y;
}));
propertyResetCallbacks.push(checkAnimation(() => {
nativeView.setTranslationX(originalValue1);
nativeView.setTranslationY(originalValue2);
}));
animatorSet = new android.animation.AnimatorSet();
animatorSet.playTogether(xyObjectAnimators);
@@ -211,21 +219,28 @@ export class Animation extends common.Animation implements definition.Animation
case common.Properties.scale:
xyObjectAnimators = java.lang.reflect.Array.newInstance(android.animation.Animator.class, 2);
originalValue = nativeView.getScaleX();
nativeArray = java.lang.reflect.Array.newInstance(floatType, 1);
nativeArray[0] = propertyAnimation.value.x;
xyObjectAnimators[0] = android.animation.ObjectAnimator.ofFloat(nativeView, "scaleX", nativeArray);
xyObjectAnimators[0].setRepeatCount(Animation._getAndroidRepeatCount(propertyAnimation.iterations));
propertyUpdateCallbacks.push(checkAnimation(() => { propertyAnimation.target.scaleX = propertyAnimation.value.x; }));
propertyResetCallbacks.push(checkAnimation(() => { nativeView.setScaleX(originalValue); }));
originalValue = nativeView.getScaleY();
nativeArray = java.lang.reflect.Array.newInstance(floatType, 1);
nativeArray[0] = propertyAnimation.value.y;
xyObjectAnimators[1] = android.animation.ObjectAnimator.ofFloat(nativeView, "scaleY", nativeArray);
xyObjectAnimators[1].setRepeatCount(Animation._getAndroidRepeatCount(propertyAnimation.iterations));
propertyUpdateCallbacks.push(checkAnimation(() => { propertyAnimation.target.scaleY = propertyAnimation.value.y; }));
propertyResetCallbacks.push(checkAnimation(() => { nativeView.setScaleY(originalValue); }));
originalValue1 = nativeView.getScaleX();
originalValue2 = nativeView.getScaleY();
propertyUpdateCallbacks.push(checkAnimation(() => {
propertyAnimation.target.scaleX = propertyAnimation.value.x;
propertyAnimation.target.scaleY = propertyAnimation.value.y;
}));
propertyResetCallbacks.push(checkAnimation(() => {
nativeView.setScaleY(originalValue1);
nativeView.setScaleY(originalValue2);
}));
animatorSet = new android.animation.AnimatorSet();
animatorSet.playTogether(xyObjectAnimators);
@@ -234,11 +249,11 @@ export class Animation extends common.Animation implements definition.Animation
break;
case common.Properties.rotate:
originalValue = nativeView.getRotation();
originalValue1 = nativeView.getRotation();
nativeArray = java.lang.reflect.Array.newInstance(floatType, 1);
nativeArray[0] = propertyAnimation.value;
propertyUpdateCallbacks.push(checkAnimation(() => { propertyAnimation.target.rotate = propertyAnimation.value; }));
propertyResetCallbacks.push(checkAnimation(() => { nativeView.setRotation(originalValue); }));
propertyResetCallbacks.push(checkAnimation(() => { nativeView.setRotation(originalValue1); }));
animators.push(android.animation.ObjectAnimator.ofFloat(nativeView, "rotation", nativeArray));
break;

View File

@@ -16,81 +16,25 @@ function onIdPropertyChanged(data: dependencyObservable.PropertyChangeData) {
view._nativeView.accessibilityIdentifier = data.newValue;
}
(<proxy.PropertyMetadata>viewCommon.View.idProperty.metadata).onSetNativeValue = onIdPropertyChanged;
function onTranslateXPropertyChanged(data: dependencyObservable.PropertyChangeData) {
function onTransfromPropertyChanged(data: dependencyObservable.PropertyChangeData) {
var view = <View>data.object;
var newTransform = CGAffineTransformIdentity;
newTransform = CGAffineTransformTranslate(newTransform, data.newValue, view.translateY);
newTransform = CGAffineTransformRotate(newTransform, view.rotate * Math.PI / 180);
newTransform = CGAffineTransformScale(newTransform, view.scaleX, view.scaleY);
if (!CGAffineTransformEqualToTransform(view._nativeView.transform, newTransform)) {
view._nativeView.transform = newTransform;
}
view._updateNativeTransform();
}
(<proxy.PropertyMetadata>viewCommon.View.translateXProperty.metadata).onSetNativeValue = onTranslateXPropertyChanged;
(<proxy.PropertyMetadata>viewCommon.View.translateXProperty.metadata).onSetNativeValue = onTransfromPropertyChanged;
(<proxy.PropertyMetadata>viewCommon.View.translateYProperty.metadata).onSetNativeValue = onTransfromPropertyChanged;
(<proxy.PropertyMetadata>viewCommon.View.scaleXProperty.metadata).onSetNativeValue = onTransfromPropertyChanged;
(<proxy.PropertyMetadata>viewCommon.View.scaleYProperty.metadata).onSetNativeValue = onTransfromPropertyChanged;
(<proxy.PropertyMetadata>viewCommon.View.rotateProperty.metadata).onSetNativeValue = onTransfromPropertyChanged;
function onTranslateYPropertyChanged(data: dependencyObservable.PropertyChangeData) {
function onOriginPropertyChanged(data: dependencyObservable.PropertyChangeData) {
var view = <View>data.object;
var newTransform = CGAffineTransformIdentity;
newTransform = CGAffineTransformTranslate(newTransform, view.translateX, data.newValue);
newTransform = CGAffineTransformRotate(newTransform, view.rotate * Math.PI / 180);
newTransform = CGAffineTransformScale(newTransform, view.scaleX, view.scaleY);
if (!CGAffineTransformEqualToTransform(view._nativeView.transform, newTransform)) {
view._nativeView.transform = newTransform;
}
view._updateOriginPoint();
}
(<proxy.PropertyMetadata>viewCommon.View.translateYProperty.metadata).onSetNativeValue = onTranslateYPropertyChanged;
function onScaleXPropertyChanged(data: dependencyObservable.PropertyChangeData) {
var view = <View>data.object;
var newTransform = CGAffineTransformIdentity;
newTransform = CGAffineTransformTranslate(newTransform, view.translateX, view.translateY);
newTransform = CGAffineTransformRotate(newTransform, view.rotate * Math.PI / 180);
newTransform = CGAffineTransformScale(newTransform, data.newValue, view.scaleY);
if (!CGAffineTransformEqualToTransform(view._nativeView.transform, newTransform)) {
view._nativeView.transform = newTransform;
}
}
(<proxy.PropertyMetadata>viewCommon.View.scaleXProperty.metadata).onSetNativeValue = onScaleXPropertyChanged;
function onScaleYPropertyChanged(data: dependencyObservable.PropertyChangeData) {
var view = <View>data.object;
var newTransform = CGAffineTransformIdentity;
newTransform = CGAffineTransformTranslate(newTransform, view.translateX, view.translateY);
newTransform = CGAffineTransformRotate(newTransform, view.rotate * Math.PI / 180);
newTransform = CGAffineTransformScale(newTransform, view.scaleX, data.newValue);
if (!CGAffineTransformEqualToTransform(view._nativeView.transform, newTransform)) {
view._nativeView.transform = newTransform;
}
}
(<proxy.PropertyMetadata>viewCommon.View.scaleYProperty.metadata).onSetNativeValue = onScaleYPropertyChanged;
function onOriginXPropertyChanged(data: dependencyObservable.PropertyChangeData) {
var view = <View>data.object;
var current = view._nativeView.layer.anchorPoint;
view._nativeView.layer.anchorPoint = CGPointMake(data.newValue, current.y);
}
(<proxy.PropertyMetadata>viewCommon.View.originXProperty.metadata).onSetNativeValue = onOriginXPropertyChanged;
function onOriginYPropertyChanged(data: dependencyObservable.PropertyChangeData) {
var view = <View>data.object;
var current = view._nativeView.layer.anchorPoint;
view._nativeView.layer.anchorPoint = CGPointMake(current.x, data.newValue);
}
(<proxy.PropertyMetadata>viewCommon.View.originYProperty.metadata).onSetNativeValue = onOriginYPropertyChanged;
function onRotatePropertyChanged(data: dependencyObservable.PropertyChangeData) {
var view = <View>data.object;
var newTransform = CGAffineTransformIdentity;
newTransform = CGAffineTransformTranslate(newTransform, view.translateX, view.translateY);
newTransform = CGAffineTransformRotate(newTransform, data.newValue * Math.PI / 180);
newTransform = CGAffineTransformScale(newTransform, view.scaleX, view.scaleY);
if (!CGAffineTransformEqualToTransform(view._nativeView.transform, newTransform)) {
view._nativeView.transform = newTransform;
}
}
(<proxy.PropertyMetadata>viewCommon.View.rotateProperty.metadata).onSetNativeValue = onRotatePropertyChanged;
(<proxy.PropertyMetadata>viewCommon.View.originXProperty.metadata).onSetNativeValue = onOriginPropertyChanged;
(<proxy.PropertyMetadata>viewCommon.View.originYProperty.metadata).onSetNativeValue = onOriginPropertyChanged;
function onIsEnabledPropertyChanged(data: dependencyObservable.PropertyChangeData) {
var view = <View>data.object;
@@ -119,7 +63,9 @@ var PFLAG_MEASURED_DIMENSION_SET = 1 << 1;
var PFLAG_LAYOUT_REQUIRED = 1 << 2;
export class View extends viewCommon.View {
private _hasTransfrom = false;
private _privateFlags: number;
private _cachedFrame: CGRect;
constructor() {
super();
@@ -249,7 +195,17 @@ export class View extends viewCommon.View {
public _setNativeViewFrame(nativeView: any, frame: any) {
if (!CGRectEqualToRect(nativeView.frame, frame)) {
trace.write(this + ", Native setFrame: = " + NSStringFromCGRect(frame), trace.categories.Layout);
nativeView.frame = frame;
this._cachedFrame = frame;
if (this._hasTransfrom) {
// Always set identity transform before setting frame;
let transform = nativeView.transform;
nativeView.transform = CGAffineTransformIdentity;
nativeView.frame = frame;
nativeView.transform = transform;
}
else {
nativeView.frame = frame;
}
var boundsOrigin = nativeView.bounds.origin;
nativeView.bounds = CGRectMake(boundsOrigin.x, boundsOrigin.y, frame.size.width, frame.size.height);
}
@@ -293,6 +249,25 @@ export class View extends viewCommon.View {
private _onBoundsChanged() {
this.style._boundsChanged();
}
public _updateNativeTransform() {
var newTransform = CGAffineTransformIdentity;
newTransform = CGAffineTransformTranslate(newTransform, this.translateX, this.translateY);
newTransform = CGAffineTransformRotate(newTransform, this.rotate * Math.PI / 180);
newTransform = CGAffineTransformScale(newTransform, this.scaleX, this.scaleY);
if (!CGAffineTransformEqualToTransform(this._nativeView.transform, newTransform)) {
this._nativeView.transform = newTransform;
this._hasTransfrom = this._nativeView && !CGAffineTransformEqualToTransform(this._nativeView.transform, CGAffineTransformIdentity);
}
}
public _updateOriginPoint() {
let newPoint = CGPointMake(this.originX, this.originY);
this._nativeView.layer.anchorPoint = newPoint;
if (this._cachedFrame) {
this._setNativeViewFrame(this._nativeView, this._cachedFrame);
}
}
}
export class CustomLayoutView extends View {