Skip to content

Commit

Permalink
feat: update view properties after animation (#11666)
Browse files Browse the repository at this point in the history
* feat(android): update view properties post-animation

Fixes TIMOB-13764

* test: update tests to handle post-animation values

* feat(ios): update view properties post-animation

Fixes TIMOB-13764

* test: validate post-animation values on ios

* docs: add note about behavior change for animations

* fix(ios): avoid applying props on autoreverse anims

* test: add test for autoreverse anim

* fix(android): don't apply end properties to autoreversed animations

Co-authored-by: ssekhri <ssekhri@axway.com>
  • Loading branch information
sgtcoolguy and ssekhri committed May 21, 2020
1 parent 08ceabe commit 3fef676
Show file tree
Hide file tree
Showing 7 changed files with 1,002 additions and 10 deletions.
Expand Up @@ -901,9 +901,16 @@ public void onAnimationCancel(Animator animator)
@SuppressWarnings("unchecked")
public void onAnimationEnd(Animator animator)
{

if (animator instanceof AnimatorSet) {
setAnimationRunningFor(view, false);
if (autoreverse == null || !autoreverse.booleanValue()) {
// Update the underlying properties post-animation if not auto-reversing
for (Object key : options.keySet()) {
String name = TiConvert.toString(key);
Object value = options.get(key);
viewProxy.setProperty(name, value);
}
}
if (callback != null) {
callback.callAsync(viewProxy.getKrollObject(), new Object[] { new KrollDict() });
}
Expand Down
4 changes: 3 additions & 1 deletion apidoc/Titanium/UI/Animation.yml
Expand Up @@ -21,10 +21,12 @@ description: |
Use the <Titanium.UI.createAnimation> method to create an animation object.
Note that when you animate a view's size or position, the actual layout properties (such as
Note that on SDKs older than 9.1.0, when you animate a view's size or position the actual layout properties (such as
`top`, `left`, `width`, `height`) are not changed by the animation. See the description of the
[animate](Titanium.UI.View.animate) method for more information.
As of 9.1.0, the animated properties should reflect their final values just before the `complete` event and/or the <Ti.UI.View.animate> callback is fired.
#### iOS Platform Notes
iOS supports both 2D and 3D matrix transformations in animations.
Expand Down
6 changes: 4 additions & 2 deletions apidoc/Titanium/UI/View.yml
Expand Up @@ -813,10 +813,12 @@ methods:
The [Animation](Titanium.UI.Animation) object or dictionary passed to this method defines
the end state for the animation, the duration of the animation, and other properties.
Note that if you use `animate` to move a view, the view's actual *position* is changed, but
Note that on SDKs older than 9.1.0 - if you use `animate` to move a view, the view's actual *position* is changed, but
its layout properties, such as `top`, `left`, `center` and so on are not changed--these
reflect the original values set by the user, not the actual position of the view.
As of SDK 9.1.0, the final values of the animation will be set on the view just before the `complete` event and/or the callback is fired.
The [rect](Titanium.UI.View.rect) property can be used to determine the actual size and
position of the view.
Expand All @@ -829,7 +831,7 @@ methods:

- name: callback
summary: Function to be invoked upon completion of the animation.
type: Callback<Object> # FIXME: iOS appears to fire with the Ti.UI.Animation object, whiel Android fires with an empty object
type: Callback<Object> # FIXME: iOS appears to fire with the Ti.UI.Animation object, while Android fires with an empty object
optional: true

- name: clearMotionEffects
Expand Down
2 changes: 2 additions & 0 deletions iphone/TitaniumKit/TitaniumKit/Sources/API/TiAnimation.h
Expand Up @@ -86,6 +86,8 @@
NSNumber *dampingRatio;
NSNumber *springVelocity;

NSDictionary *properties;

// this is a temporary function passed in
ListenerEntry *callback;

Expand Down
15 changes: 14 additions & 1 deletion iphone/TitaniumKit/TitaniumKit/Sources/API/TiAnimation.m
Expand Up @@ -26,9 +26,11 @@ @implementation TiAnimation
@synthesize visible, curve, repeat, autoreverse, delay, transform, transition, dampingRatio, springVelocity;
@synthesize animatedView, callback, isReverse, reverseAnimation, resetState;

- (id)initWithDictionary:(NSDictionary *)properties context:(id<TiEvaluator>)context_ callback:(KrollCallback *)callback_
- (id)initWithDictionary:(NSDictionary *)properties_ context:(id<TiEvaluator>)context_ callback:(KrollCallback *)callback_
{
if (self = [super _initWithPageContext:context_]) {
// store the properties until animation is done
properties = [properties_ copy];
#define SET_FLOAT_PROP(p, d) \
{ \
id v = d == nil ? nil : [d objectForKey:@ #p]; \
Expand Down Expand Up @@ -157,6 +159,7 @@ - (void)dealloc
RELEASE_TO_NIL(view);
RELEASE_TO_NIL(dampingRatio);
RELEASE_TO_NIL(springVelocity);
RELEASE_TO_NIL(properties);
[animatedViewProxy release];
[super dealloc];
}
Expand Down Expand Up @@ -277,6 +280,15 @@ - (void)animationCompleted:(NSString *)animationID finished:(NSNumber *)finished
[animation.delegate animationWillComplete:self];
}

// Update the modified properties on the view!
if (animatedViewProxy != nil) {
if (!isReverse && ![autoreverse boolValue] && properties != nil) {
[animatedViewProxy applyProperties:properties];
}
// TODO: What about center?
RELEASE_TO_NIL(properties);
}

// fire the event and call the callback
if ([animation _hasListeners:@"complete"]) {
[animation fireEvent:@"complete" withObject:nil];
Expand Down Expand Up @@ -624,6 +636,7 @@ - (void)animate:(id)args
[self animationCompleted:[self description] finished:[NSNumber numberWithBool:finished] context:self];
}
};

if (dampingRatio != nil || springVelocity != nil) {
[UIView animateWithDuration:animationDuration
delay:([delay doubleValue] / 1000)
Expand Down
9 changes: 4 additions & 5 deletions tests/Resources/ti.ui.label.addontest.js
Expand Up @@ -39,7 +39,7 @@ describe('Titanium.UI.Label', function () {
}
});

it.allBroken('animate font color', function (finish) {
it('animate font color', function (finish) {
win = Ti.UI.createWindow();

const label = Ti.UI.createLabel({
Expand All @@ -51,11 +51,10 @@ describe('Titanium.UI.Label', function () {
duration: 1000
});
animation.addEventListener('complete', function () {
// FIXME: iOS appears to be firing this event immediately, not when the animation is actually done!
// test takes 206 ms, but fastest it could run is 1200ms due to 1s animation value
// FIXME: iOS fires right away because text color doesn't transition over time, it just changes immediately.
// See https://stackoverflow.com/questions/2426614/how-to-animate-the-textcolor-property-of-an-uilabel
try {
should(label.color).be.eql('#fff'); // FIXME: animations don't update the view's properties when they complete!
// This is a longstanding issue and should be addressed
should(label.color).be.eql('#fff');
} catch (err) {
return finish(err);
}
Expand Down

0 comments on commit 3fef676

Please sign in to comment.