-
Notifications
You must be signed in to change notification settings - Fork 47
feat: add loop animation support for Phase and Keyframe animations #824
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
5c74f70
aa6c970
d7ddd51
1c701e1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -239,6 +239,9 @@ class PhaseAnimationDriver<S extends Spec<S>> extends StyleAnimationDriver<S> { | |
| required this.context, | ||
| }) { | ||
| _setUpAnimation(); | ||
| if (_isLooping) { | ||
| _startLoopingAnimation(); | ||
| } | ||
| } | ||
|
|
||
| void _setUpAnimation() { | ||
|
|
@@ -251,7 +254,7 @@ class PhaseAnimationDriver<S extends Spec<S>> extends StyleAnimationDriver<S> { | |
| // Override the animation to use TweenSequence wrapped in a tween | ||
| _animation = controller.drive(_PhasedSpecTween(_tweenSequence)); | ||
|
|
||
| config.trigger.addListener(_onTriggerChanged); | ||
| config.trigger?.addListener(_onTriggerChanged); | ||
|
|
||
| // Add status listener for onEnd callback | ||
| if (config.curveConfigs.last.onEnd != null) { | ||
|
|
@@ -301,6 +304,13 @@ class PhaseAnimationDriver<S extends Spec<S>> extends StyleAnimationDriver<S> { | |
| return TweenSequence(items); | ||
| } | ||
|
|
||
| void _startLoopingAnimation() { | ||
| controller.duration = totalDuration; | ||
| controller.repeat(); | ||
| } | ||
|
|
||
| bool get _isLooping => config.trigger == null; | ||
|
|
||
| /// Gets the total duration of all animation phases combined. | ||
| Duration get totalDuration { | ||
| return config.curveConfigs.fold( | ||
|
|
@@ -311,7 +321,8 @@ class PhaseAnimationDriver<S extends Spec<S>> extends StyleAnimationDriver<S> { | |
|
|
||
| @override | ||
| void dispose() { | ||
| config.trigger.removeListener(_onTriggerChanged); | ||
| config.trigger?.removeListener(_onTriggerChanged); | ||
| controller.stop(); | ||
| super.dispose(); | ||
| } | ||
|
|
||
|
|
@@ -324,8 +335,12 @@ class PhaseAnimationDriver<S extends Spec<S>> extends StyleAnimationDriver<S> { | |
|
|
||
| @override | ||
| void updateDriver(covariant PhaseAnimationConfig config) { | ||
| config.trigger.removeListener(_onTriggerChanged); | ||
| this.config.trigger?.removeListener(_onTriggerChanged); | ||
| this.config = config; | ||
| controller.reset(); | ||
| if (_isLooping) { | ||
| _startLoopingAnimation(); | ||
| } | ||
| _setUpAnimation(); | ||
| } | ||
| } | ||
|
|
@@ -345,6 +360,9 @@ class KeyframeAnimationDriver<S extends Spec<S>> | |
| required this.context, | ||
| }) : _config = config { | ||
| _setUpAnimation(); | ||
| if (_isLooping) { | ||
| _startLoopingAnimation(); | ||
| } | ||
| } | ||
|
|
||
| void _onTriggerChanged() { | ||
|
|
@@ -361,9 +379,16 @@ class KeyframeAnimationDriver<S extends Spec<S>> | |
| _KeyframeAnimatable(_sequenceMap, _config, context), | ||
| ); | ||
|
|
||
| _config.trigger.addListener(_onTriggerChanged); | ||
| _config.trigger?.addListener(_onTriggerChanged); | ||
| } | ||
|
|
||
| void _startLoopingAnimation() { | ||
| controller.duration = duration; | ||
| controller.repeat(); | ||
| } | ||
|
|
||
| bool get _isLooping => _config.trigger == null; | ||
|
|
||
| Duration get duration { | ||
| if (_config.timeline.isEmpty) return .zero; | ||
|
|
||
|
|
@@ -375,7 +400,8 @@ class KeyframeAnimationDriver<S extends Spec<S>> | |
|
|
||
| @override | ||
| void dispose() { | ||
| _config.trigger.removeListener(_onTriggerChanged); | ||
| _config.trigger?.removeListener(_onTriggerChanged); | ||
| controller.stop(); | ||
| super.dispose(); | ||
| } | ||
|
|
||
|
|
@@ -392,8 +418,12 @@ class KeyframeAnimationDriver<S extends Spec<S>> | |
|
|
||
| @override | ||
| void updateDriver(covariant KeyframeAnimationConfig<S> config) { | ||
| _config.trigger.removeListener(_onTriggerChanged); | ||
| _config.trigger?.removeListener(_onTriggerChanged); | ||
|
||
| _config = config; | ||
| controller.reset(); | ||
| if (_isLooping) { | ||
| _startLoopingAnimation(); | ||
| } | ||
| _setUpAnimation(); | ||
| } | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
_isLoopingcheck uses the old config's trigger value instead of the new config's trigger value. The check on line 339 evaluates_isLoopingwhich accessesthis.config.trigger, butthis.configis not updated until line 343. This means:The old trigger listener is removed using the new config parameter (line 338), but the looping check uses the old config. Either check
_isLoopingafter updatingthis.config, or check the new config parameter directly withconfig.trigger == null.