@@ -45,9 +45,11 @@ extension AnimatedEffectExt on Widget? {
4545 ///
4646 /// The [delay] parameter is used to set a delay before the animation starts.
4747 ///
48- /// The [startImmediately] parameter is used to determine whether the
49- /// animation should be triggered immediately when the widget is built,
50- /// ignoring the value of [trigger] initially.
48+ /// The [resetValues] parameter is used to determine whether the animation
49+ /// should start from idle values or from the current state of the widget.
50+ ///
51+ /// The [startState] parameter is used to determine the behavior of the
52+ /// animation as soon as it is added to the widget tree.
5153 ///
5254 /// The [playIf] parameter is used to determine whether the animation should
5355 /// be played or skipped. If the callback returns false, the animation will
@@ -62,11 +64,10 @@ extension AnimatedEffectExt on Widget? {
6264 Curve curve = appleEaseInOut,
6365 int repeat = 0 ,
6466 bool reverse = false ,
65- bool startImmediately = false ,
66- bool skipFirstTime = false ,
6767 bool resetValues = false ,
6868 bool waitForLastAnimation = false ,
6969 Duration delay = Duration .zero,
70+ AnimationStartState startState = AnimationStartState .idle,
7071 VoidCallback ? onEnd,
7172 BooleanCallback ? playIf,
7273 BooleanCallback ? skipIf,
@@ -78,11 +79,10 @@ extension AnimatedEffectExt on Widget? {
7879 curve: curve,
7980 repeat: repeat,
8081 reverse: reverse,
81- startImmediately: startImmediately,
82- skipFirstTime: skipFirstTime,
8382 resetValues: resetValues,
8483 waitForLastAnimation: waitForLastAnimation,
8584 delay: delay,
85+ startState: startState,
8686 onEnd: onEnd,
8787 playIf: playIf,
8888 skipIf: skipIf,
@@ -232,6 +232,26 @@ extension AnimatedEffectExt on Widget? {
232232 Widget resetAll () => ResetAllAnimationsEffect (child: this );
233233}
234234
235+ /// Determines the behavior of the [AnimatedEffect] as soon as it is added
236+ /// to the widget tree.
237+ enum AnimationStartState {
238+ /// As soon as the animation is inserted into the widget tree, it will
239+ /// start playing the animation from the beginning to the end. Before
240+ /// the trigger Object changes.
241+ playImmediately,
242+
243+ /// The animation will be inserted into the widget tree but will not
244+ /// start playing. It will instead trigger the effects in the chain
245+ /// to their ending values as soon as it is inserted.
246+ /// The "current" values of the effect chain are used
247+ /// immediately as initial values.
248+ useCurrentValues,
249+
250+ /// As soon as the animation is inserted into the widget tree, none of
251+ /// the effects will be triggered in any state.
252+ idle;
253+ }
254+
235255/// A widget that animates the effects applied to it's child.
236256class AnimatedEffect extends StatefulWidget {
237257 /// The widget below this widget in the tree.
@@ -244,6 +264,10 @@ class AnimatedEffect extends StatefulWidget {
244264 /// Defines how the animation is fired.
245265 final AnimationTriggerType triggerType;
246266
267+ /// Determines the behavior of this [AnimatedEffect] as soon as it is added
268+ /// to the widget tree.
269+ final AnimationStartState startState;
270+
247271 /// The duration of the animation.
248272 final Duration duration;
249273
@@ -259,12 +283,6 @@ class AnimatedEffect extends StatefulWidget {
259283 /// Whether the animation should be reversed after each repetition.
260284 final bool reverse;
261285
262- /// Whether the animation should be triggered immediately when the widget is
263- /// built, ignoring the value of [trigger] initially.
264- final bool startImmediately;
265-
266- final bool skipFirstTime;
267-
268286 /// Normally, an effect represents the current state of the widget and this
269287 /// animate effect is only in charge of lerping between states of those
270288 /// effect values.
@@ -299,13 +317,12 @@ class AnimatedEffect extends StatefulWidget {
299317 required this .child,
300318 required this .duration,
301319 required this .triggerType,
320+ this .startState = AnimationStartState .idle,
302321 this .trigger,
303322 this .curve = appleEaseInOut,
304323 this .onEnd,
305324 this .repeat = 0 ,
306325 this .reverse = false ,
307- this .startImmediately = false ,
308- this .skipFirstTime = false ,
309326 this .resetValues = false ,
310327 this .waitForLastAnimation = false ,
311328 this .delay = Duration .zero,
@@ -339,7 +356,10 @@ class AnimatedEffectState extends State<AnimatedEffect>
339356 /// The animation controller that drives the animation.
340357 late final AnimationController controller = AnimationController (
341358 vsync: this ,
342- value: widget.skipFirstTime || shouldSkip ? 1 : 0 ,
359+ value:
360+ widget.startState == AnimationStartState .useCurrentValues || shouldSkip
361+ ? 1
362+ : 0 ,
343363 duration: widget.duration,
344364 );
345365
@@ -359,21 +379,21 @@ class AnimatedEffectState extends State<AnimatedEffect>
359379 if (didPlay) return ;
360380
361381 if (widget.key case Key key) {
362- final persister = AnimatedEffectStateRetainer .maybeOf (context);
363- final alreadyPlayed = persister ? .didPlay (key) ?? false ;
382+ final retainer = AnimatedEffectStateRetainer .maybeOf (context);
383+ final alreadyPlayed = retainer ? .didPlay (key) ?? false ;
364384 if (alreadyPlayed) {
365385 // If the animation has already played, end it immediately.
366386 controller.value = 1 ;
367387 return ;
368388 }
369389
370- persister ? .markAsPlayed (key);
390+ retainer ? .markAsPlayed (key);
371391 }
372392
373393 // If the trigger type is one shot or trigger immediately is true,
374394 // drive the animation.
375395 if (widget.triggerType == AnimationTriggerType .oneShot ||
376- widget.startImmediately ) {
396+ widget.startState == AnimationStartState .playImmediately ) {
377397 drive ();
378398 didPlay = false ;
379399 }
@@ -431,7 +451,7 @@ class AnimatedEffectState extends State<AnimatedEffect>
431451 // ancestor's [AnimationTriggerType] is
432452 // [AnimationTriggerType.afterLast].
433453 final AnimatedEffectState ? parentState =
434- context.findAncestorStateOfType <AnimatedEffectState >();
454+ context.findAncestorStateOfType <AnimatedEffectState >();
435455 final AnimationTriggerType ? triggerType =
436456 parentState? .widget.triggerType;
437457 if (parentState != null &&
@@ -443,7 +463,7 @@ class AnimatedEffectState extends State<AnimatedEffect>
443463 // [ResetAllAnimationsEffect], reset all animations in the chain.
444464 else {
445465 final resetState =
446- context.findAncestorStateOfType <ResetAllAnimationsEffectState >();
466+ context.findAncestorStateOfType <ResetAllAnimationsEffectState >();
447467 resetState? .reset ();
448468 }
449469 }
@@ -500,16 +520,15 @@ class AnimatedEffectState extends State<AnimatedEffect>
500520 Widget build (BuildContext context) {
501521 return AnimatedBuilder (
502522 animation: controller,
503- builder: (context, child) =>
504- EffectQuery (
505- linearValue: controller.value,
506- curvedValue: widget.curve.transform (controller.value),
507- isTransition: false ,
508- resetValues: widget.resetValues,
509- duration: widget.duration,
510- curve: widget.curve,
511- child: child! ,
512- ),
523+ builder: (context, child) => EffectQuery (
524+ linearValue: controller.value,
525+ curvedValue: widget.curve.transform (controller.value),
526+ isTransition: false ,
527+ resetValues: widget.resetValues,
528+ duration: widget.duration,
529+ curve: widget.curve,
530+ child: child! ,
531+ ),
513532 child: widget.child,
514533 );
515534 }
0 commit comments