diff --git a/Android/doric/src/main/java/pub/doric/shader/ViewNode.java b/Android/doric/src/main/java/pub/doric/shader/ViewNode.java index a92a7cd5..e11360c4 100644 --- a/Android/doric/src/main/java/pub/doric/shader/ViewNode.java +++ b/Android/doric/src/main/java/pub/doric/shader/ViewNode.java @@ -665,8 +665,20 @@ public abstract class ViewNode extends DoricContextHolder { } else if (value.isObject()) { JSArray changeables = value.asObject().getProperty("changeables").asArray(); AnimatorSet animatorSet = new AnimatorSet(); + + JSValue repeatCount = value.asObject().getProperty("repeatCount"); + + JSValue repeatMode = value.asObject().getProperty("repeatMode"); + for (int j = 0; j < changeables.size(); j++) { - animatorSet.play(parseChangeable(changeables.get(j).asObject())); + ObjectAnimator animator = parseChangeable(changeables.get(j).asObject()); + if (repeatCount.isNumber()) { + animator.setRepeatCount(repeatCount.asNumber().toInt()); + } + if (repeatMode.isNumber()) { + animator.setRepeatMode(repeatMode.asNumber().toInt()); + } + animatorSet.play(animator); } long duration = value.asObject().getProperty("duration").asNumber().toLong(); animatorSet.setDuration(duration); @@ -674,27 +686,19 @@ public abstract class ViewNode extends DoricContextHolder { if (delayJS.isNumber()) { animatorSet.setStartDelay(delayJS.asNumber().toLong()); } + return animatorSet; } else { return null; } } - private Animator parseChangeable(JSObject jsObject) { + private ObjectAnimator parseChangeable(JSObject jsObject) { String key = jsObject.getProperty("key").asString().value(); - ObjectAnimator animator = ObjectAnimator.ofFloat(this, + return ObjectAnimator.ofFloat(this, key, jsObject.getProperty("fromValue").asNumber().toFloat(), jsObject.getProperty("toValue").asNumber().toFloat() ); - JSValue repeatCount = jsObject.getProperty("repeatCount"); - if (repeatCount.isNumber()) { - animator.setRepeatCount(repeatCount.asNumber().toInt() + 1); - } - JSValue repeatMode = jsObject.getProperty("repeatMode"); - if (repeatMode.isNumber()) { - animator.setRepeatMode(repeatMode.asNumber().toInt()); - } - return animator; } } diff --git a/demo/src/AnimatorDemo.ts b/demo/src/AnimatorDemo.ts index 1b067fd5..e3792f7b 100644 --- a/demo/src/AnimatorDemo.ts +++ b/demo/src/AnimatorDemo.ts @@ -174,7 +174,7 @@ class AnimatorDemo extends Panel { translate.fromTranslationY = 10 translate.toTranslationY = 200 translate.duration = 3000 - + translate.delay = 1000 const scale = new ScaleAnimation scale.fromScaleX = 1 scale.toScaleX = 5 @@ -185,13 +185,16 @@ class AnimatorDemo extends Panel { const rotation = new RotationAnimation rotation.fromRotation = 0 rotation.toRotation = 6 + rotation.delay = 1000 rotation.duration = 3000 animationSet.addAnimation(translate) animationSet.addAnimation(scale) animationSet.addAnimation(rotation) - view.doAnimation(context, animationSet) + view.doAnimation(context, animationSet).then(() => { + modal(context).toast('Animation finished') + }) } }), ]).apply({ space: 10 } as IHLayout), diff --git a/iOS/Pod/Classes/Shader/DoricViewNode.m b/iOS/Pod/Classes/Shader/DoricViewNode.m index fc6f87ae..381b52ba 100644 --- a/iOS/Pod/Classes/Shader/DoricViewNode.m +++ b/iOS/Pod/Classes/Shader/DoricViewNode.m @@ -317,6 +317,14 @@ - (void)doAnimation:(id)params withPromise:(DoricPromise *)promise { [self.view.layer addAnimation:animation forKey:nil]; } +- (CFTimeInterval)computeDurationOfAnimations:(NSArray *)animations { + __block CFTimeInterval interval = 0; + [animations forEach:^(CAAnimation *obj) { + interval = MAX(interval, obj.beginTime + obj.duration * (1 + obj.repeatCount)); + }]; + return interval; +} + - (CAAnimation *)parseAnimation:(id)params { if ([params isKindOfClass:[NSArray class]]) { NSArray *anims = params; @@ -325,6 +333,7 @@ - (CAAnimation *)parseAnimation:(id)params { [anims forEach:^(id obj) { [animations addObject:[self parseAnimation:obj]]; }]; + animationGroup.duration = [self computeDurationOfAnimations:animations]; animationGroup.animations = animations; return animationGroup; } else if ([params isKindOfClass:[NSDictionary class]]) { @@ -346,6 +355,7 @@ - (CAAnimation *)parseAnimation:(id)params { }]; animation.fromValue = [NSValue valueWithCGPoint:from]; animation.toValue = [NSValue valueWithCGPoint:to]; + [self setAnimation:animation params:params]; return animation; } else { CAAnimationGroup *animationGroup = [CAAnimationGroup animation]; @@ -354,19 +364,34 @@ - (CAAnimation *)parseAnimation:(id)params { [animations addObject:[self parseChangeable:obj]]; }]; animationGroup.animations = animations; - animationGroup.duration = [params[@"duration"] floatValue] / 1000; - if (params[@"delay"]) { - animationGroup.beginTime = CACurrentMediaTime() + [params[@"delay"] floatValue] / 1000; - } - + [self setAnimation:animationGroup params:params]; return animationGroup; } - - } return nil; } +- (void)setAnimation:(CAAnimation *)animation params:(NSDictionary *)params { + if (params[@"repeatCount"]) { + NSInteger repeatCount = [params[@"repeatCount"] integerValue]; + if (repeatCount < 0) { + repeatCount = NSNotFound; + } + animation.repeatCount = repeatCount; + } + if (params[@"repeatMode"]) { + NSInteger repeatMode = [params[@"repeatMode"] integerValue]; + animation.autoreverses = repeatMode == 2; + } + + if (params[@"delay"]) { + animation.beginTime = [params[@"delay"] floatValue] / 1000; + } + animation.duration = [params[@"duration"] floatValue] / 1000; + animation.removedOnCompletion = NO; + animation.fillMode = kCAFillModeForwards; +} + - (CAAnimation *)parseChangeable:(NSDictionary *)params { NSString *key = params[@"key"]; CABasicAnimation *animation = [CABasicAnimation animation]; @@ -387,17 +412,6 @@ - (CAAnimation *)parseChangeable:(NSDictionary *)params { animation.fromValue = params[@"fromValue"]; animation.toValue = params[@"toValue"]; } - if (params[@"repeatCount"]) { - NSInteger repeatCount = [params[@"repeatCount"] integerValue]; - if (repeatCount < 0) { - repeatCount = NSNotFound; - } - animation.repeatCount = repeatCount; - } - if (params[@"repeatMode"]) { - NSInteger repeatMode = [params[@"repeatMode"] integerValue]; - animation.autoreverses = repeatMode == 2; - } return animation; } diff --git a/js-framework/src/ui/animation.ts b/js-framework/src/ui/animation.ts index 15fea10a..e32546a9 100644 --- a/js-framework/src/ui/animation.ts +++ b/js-framework/src/ui/animation.ts @@ -49,8 +49,6 @@ abstract class Animation implements IAnimation { key: e.key, fromValue: e.fromValue, toValue: e.toValue, - repeatCount: this.repeatCount, - repeatMode: this.repeatMode, }) } return { @@ -58,6 +56,8 @@ abstract class Animation implements IAnimation { delay: this.delay, duration: this.duration, changeables, + repeatCount: this.repeatCount, + repeatMode: this.repeatMode, } } }