Merge pull request #1501 from NativeScript/raikov/issue-1218

Fixed: Setting and instantly animating a property fails for iOS
This commit is contained in:
tzraikov
2016-02-05 15:10:19 +02:00
2 changed files with 45 additions and 8 deletions

View File

@ -29,6 +29,9 @@ class AnimationDelegateImpl extends NSObject {
var nativeView = <UIView>this._propertyAnimation.target._nativeView; var nativeView = <UIView>this._propertyAnimation.target._nativeView;
var propertyNameToAnimate = this._propertyAnimation.property; var propertyNameToAnimate = this._propertyAnimation.property;
var value = this._propertyAnimation.value; var value = this._propertyAnimation.value;
(<any>this._propertyAnimation.target)._suspendPresentationLayerUpdates();
switch (this._propertyAnimation.property) { switch (this._propertyAnimation.property) {
case common.Properties.backgroundColor: case common.Properties.backgroundColor:
this._propertyAnimation.target.backgroundColor = value; this._propertyAnimation.target.backgroundColor = value;
@ -50,6 +53,9 @@ class AnimationDelegateImpl extends NSObject {
} }
break; break;
} }
(<any>this._propertyAnimation.target)._resumePresentationLayerUpdates();
} }
public animationDidStopFinished(anim: CAAnimation, flag: boolean): void { public animationDidStopFinished(anim: CAAnimation, flag: boolean): void {

View File

@ -71,6 +71,7 @@ export class View extends viewCommon.View {
private _hasTransfrom = false; private _hasTransfrom = false;
private _privateFlags: number; private _privateFlags: number;
private _cachedFrame: CGRect; private _cachedFrame: CGRect;
private _suspendCATransaction = false;
constructor() { constructor() {
super(); super();
@ -92,7 +93,7 @@ export class View extends viewCommon.View {
public onLoaded() { public onLoaded() {
super.onLoaded(); super.onLoaded();
// TODO: It is very late to work with options here in the onLoaded method. // TODO: It is very late to work with options here in the onLoaded method.
// We should not do anything that affects UI AFTER the widget has been loaded. // We should not do anything that affects UI AFTER the widget has been loaded.
utils.copyFrom(this._options, this); utils.copyFrom(this._options, this);
delete this._options; delete this._options;
@ -126,7 +127,7 @@ export class View extends viewCommon.View {
var measureSpecsChanged = this._setCurrentMeasureSpecs(widthMeasureSpec, heightMeasureSpec); var measureSpecsChanged = this._setCurrentMeasureSpecs(widthMeasureSpec, heightMeasureSpec);
var forceLayout = (this._privateFlags & PFLAG_FORCE_LAYOUT) === PFLAG_FORCE_LAYOUT; var forceLayout = (this._privateFlags & PFLAG_FORCE_LAYOUT) === PFLAG_FORCE_LAYOUT;
if (forceLayout || measureSpecsChanged) { if (forceLayout || measureSpecsChanged) {
// first clears the measured dimension flag // first clears the measured dimension flag
this._privateFlags &= ~PFLAG_MEASURED_DIMENSION_SET; this._privateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
@ -223,7 +224,7 @@ export class View extends viewCommon.View {
} }
// This is done because when rotated in iOS7 there is rotation applied on the first subview on the Window which is our frame.nativeView.view. // This is done because when rotated in iOS7 there is rotation applied on the first subview on the Window which is our frame.nativeView.view.
// If we set it it should be transformed so it is correct. // If we set it it should be transformed so it is correct.
// When in landscape in iOS 7 there is transformation on the first subview of the window so we set frame to its subview. // When in landscape in iOS 7 there is transformation on the first subview of the window so we set frame to its subview.
// in iOS 8 we set frame to subview again otherwise we get clipped. // in iOS 8 we set frame to subview again otherwise we get clipped.
var nativeView: UIView; var nativeView: UIView;
@ -285,7 +286,7 @@ export class View extends viewCommon.View {
return true; return true;
} }
return false; return false;
} }
@ -293,8 +294,23 @@ export class View extends viewCommon.View {
if (this._nativeView) { if (this._nativeView) {
this._nativeView.removeFromSuperview(); this._nativeView.removeFromSuperview();
} }
} }
}
// By default we update the view's presentation layer when setting backgroundColor and opacity properties.
// This is done by calling CATransaction begin and commit methods.
// This action should be disabled when updating those properties during an animation.
public _suspendPresentationLayerUpdates() {
this._suspendCATransaction = true;
}
public _resumePresentationLayerUpdates() {
this._suspendCATransaction = false;
}
public _isPresentationLayerUpdateSuspeneded() {
return this._suspendCATransaction;
}
}
export class CustomLayoutView extends View { export class CustomLayoutView extends View {
@ -336,7 +352,14 @@ export class ViewStyler implements style.Styler {
var nativeView: UIView = <UIView>view._nativeView; var nativeView: UIView = <UIView>view._nativeView;
if (nativeView) { if (nativeView) {
ensureBackground(); ensureBackground();
var updateSuspended = view._isPresentationLayerUpdateSuspeneded();
if (!updateSuspended) {
CATransaction.begin();
}
nativeView.backgroundColor = background.ios.createBackgroundUIColor(view); nativeView.backgroundColor = background.ios.createBackgroundUIColor(view);
if (!updateSuspended) {
CATransaction.commit();
}
} }
} }
@ -374,7 +397,15 @@ export class ViewStyler implements style.Styler {
private static setOpacityProperty(view: View, newValue: any) { private static setOpacityProperty(view: View, newValue: any) {
var nativeView: UIView = <UIView>view._nativeView; var nativeView: UIView = <UIView>view._nativeView;
if (nativeView) { if (nativeView) {
return nativeView.alpha = newValue; var updateSuspended = view._isPresentationLayerUpdateSuspeneded();
if (!updateSuspended) {
CATransaction.begin();
}
var alpha = nativeView.alpha = newValue;
if (!updateSuspended) {
CATransaction.commit();
}
return alpha;
} }
} }
@ -477,4 +508,4 @@ export class ViewStyler implements style.Styler {
} }
} }
ViewStyler.registerHandlers(); ViewStyler.registerHandlers();