Commit d4a01644 authored by Robin Jespersen's avatar Robin Jespersen Committed by Kate Lovett

Adding onEnd callback to implicit animated widgets (#38979)

parent 4373a319
......@@ -227,10 +227,11 @@ class AnimatedTheme extends ImplicitlyAnimatedWidget {
this.isMaterialAppTheme = false,
Curve curve = Curves.linear,
Duration duration = kThemeAnimationDuration,
VoidCallback onEnd,
@required this.child,
}) : assert(child != null),
assert(data != null),
super(key: key, curve: curve, duration: duration);
super(key: key, curve: curve, duration: duration, onEnd: onEnd);
/// Specifies the color and typography values for descendant widgets.
final ThemeData data;
......
......@@ -276,6 +276,7 @@ abstract class ImplicitlyAnimatedWidget extends StatefulWidget {
Key key,
this.curve = Curves.linear,
@required this.duration,
this.onEnd,
}) : assert(curve != null),
assert(duration != null),
super(key: key);
......@@ -286,6 +287,12 @@ abstract class ImplicitlyAnimatedWidget extends StatefulWidget {
/// The duration over which to animate the parameters of this container.
final Duration duration;
/// Called every time an animation completes.
///
/// This can be useful to trigger additional actions (e.g. another animation)
/// at the end of the current animation.
final VoidCallback onEnd;
@override
ImplicitlyAnimatedWidgetState<ImplicitlyAnimatedWidget> createState();
......@@ -356,6 +363,17 @@ abstract class ImplicitlyAnimatedWidgetState<T extends ImplicitlyAnimatedWidget>
debugLabel: kDebugMode ? '${widget.toStringShort()}' : null,
vsync: this,
);
_controller.addStatusListener((AnimationStatus status) {
switch (status) {
case AnimationStatus.completed:
if (widget.onEnd != null)
widget.onEnd();
break;
case AnimationStatus.dismissed:
case AnimationStatus.forward:
case AnimationStatus.reverse:
}
});
_updateCurve();
_constructTweens();
didUpdateTweens();
......@@ -624,6 +642,7 @@ class AnimatedContainer extends ImplicitlyAnimatedWidget {
this.child,
Curve curve = Curves.linear,
@required Duration duration,
VoidCallback onEnd,
}) : assert(margin == null || margin.isNonNegative),
assert(padding == null || padding.isNonNegative),
assert(decoration == null || decoration.debugAssertIsValid()),
......@@ -638,7 +657,7 @@ class AnimatedContainer extends ImplicitlyAnimatedWidget {
? constraints?.tighten(width: width, height: height)
?? BoxConstraints.tightFor(width: width, height: height)
: constraints,
super(key: key, curve: curve, duration: duration);
super(key: key, curve: curve, duration: duration, onEnd: onEnd);
/// The [child] contained by the container.
///
......@@ -780,9 +799,10 @@ class AnimatedPadding extends ImplicitlyAnimatedWidget {
this.child,
Curve curve = Curves.linear,
@required Duration duration,
VoidCallback onEnd,
}) : assert(padding != null),
assert(padding.isNonNegative),
super(key: key, curve: curve, duration: duration);
super(key: key, curve: curve, duration: duration, onEnd: onEnd);
/// The amount of space by which to inset the child.
final EdgeInsetsGeometry padding;
......@@ -859,8 +879,9 @@ class AnimatedAlign extends ImplicitlyAnimatedWidget {
this.child,
Curve curve = Curves.linear,
@required Duration duration,
VoidCallback onEnd,
}) : assert(alignment != null),
super(key: key, curve: curve, duration: duration);
super(key: key, curve: curve, duration: duration, onEnd: onEnd);
/// How to align the child.
///
......@@ -967,9 +988,10 @@ class AnimatedPositioned extends ImplicitlyAnimatedWidget {
this.height,
Curve curve = Curves.linear,
@required Duration duration,
VoidCallback onEnd,
}) : assert(left == null || right == null || width == null),
assert(top == null || bottom == null || height == null),
super(key: key, curve: curve, duration: duration);
super(key: key, curve: curve, duration: duration, onEnd: onEnd);
/// Creates a widget that animates the rectangle it occupies implicitly.
///
......@@ -980,13 +1002,14 @@ class AnimatedPositioned extends ImplicitlyAnimatedWidget {
Rect rect,
Curve curve = Curves.linear,
@required Duration duration,
VoidCallback onEnd,
}) : left = rect.left,
top = rect.top,
width = rect.width,
height = rect.height,
right = null,
bottom = null,
super(key: key, curve: curve, duration: duration);
super(key: key, curve: curve, duration: duration, onEnd: onEnd);
/// The widget below this widget in the tree.
///
......@@ -1118,9 +1141,10 @@ class AnimatedPositionedDirectional extends ImplicitlyAnimatedWidget {
this.height,
Curve curve = Curves.linear,
@required Duration duration,
VoidCallback onEnd,
}) : assert(start == null || end == null || width == null),
assert(top == null || bottom == null || height == null),
super(key: key, curve: curve, duration: duration);
super(key: key, curve: curve, duration: duration, onEnd: onEnd);
/// The widget below this widget in the tree.
///
......@@ -1274,9 +1298,10 @@ class AnimatedOpacity extends ImplicitlyAnimatedWidget {
@required this.opacity,
Curve curve = Curves.linear,
@required Duration duration,
VoidCallback onEnd,
this.alwaysIncludeSemantics = false,
}) : assert(opacity != null && opacity >= 0.0 && opacity <= 1.0),
super(key: key, curve: curve, duration: duration);
super(key: key, curve: curve, duration: duration, onEnd: onEnd);
/// The widget below this widget in the tree.
///
......@@ -1369,12 +1394,13 @@ class AnimatedDefaultTextStyle extends ImplicitlyAnimatedWidget {
this.maxLines,
Curve curve = Curves.linear,
@required Duration duration,
VoidCallback onEnd,
}) : assert(style != null),
assert(child != null),
assert(softWrap != null),
assert(overflow != null),
assert(maxLines == null || maxLines > 0),
super(key: key, curve: curve, duration: duration);
super(key: key, curve: curve, duration: duration, onEnd: onEnd);
/// The widget below this widget in the tree.
///
......@@ -1484,6 +1510,7 @@ class AnimatedPhysicalModel extends ImplicitlyAnimatedWidget {
this.animateShadowColor = true,
Curve curve = Curves.linear,
@required Duration duration,
VoidCallback onEnd,
}) : assert(child != null),
assert(shape != null),
assert(clipBehavior != null),
......@@ -1493,7 +1520,7 @@ class AnimatedPhysicalModel extends ImplicitlyAnimatedWidget {
assert(shadowColor != null),
assert(animateColor != null),
assert(animateShadowColor != null),
super(key: key, curve: curve, duration: duration);
super(key: key, curve: curve, duration: duration, onEnd: onEnd);
/// The widget below this widget in the tree.
///
......
......@@ -127,12 +127,12 @@ class TweenAnimationBuilder<T> extends ImplicitlyAnimatedWidget {
@required Duration duration,
Curve curve = Curves.linear,
@required this.builder,
this.onEnd,
VoidCallback onEnd,
this.child,
}) : assert(tween != null),
assert(curve != null),
assert(builder != null),
super(key: key, duration: duration, curve: curve);
super(key: key, duration: duration, curve: curve, onEnd: onEnd);
/// Defines the target value for the animation.
///
......@@ -186,12 +186,6 @@ class TweenAnimationBuilder<T> extends ImplicitlyAnimatedWidget {
/// performance significantly in some cases and is therefore a good practice.
final Widget child;
/// Called every time an animation completes.
///
/// This can be useful to trigger additional actions (e.g. another animation)
/// at the end of the current animation.
final VoidCallback onEnd;
@override
ImplicitlyAnimatedWidgetState<ImplicitlyAnimatedWidget> createState() {
return _TweenAnimationBuilderState<T>();
......@@ -206,27 +200,11 @@ class _TweenAnimationBuilderState<T> extends AnimatedWidgetBaseState<TweenAnimat
_currentTween = widget.tween;
_currentTween.begin ??= _currentTween.end;
super.initState();
// The statusListener is removed when the superclass disposes the controller.
controller.addStatusListener(_onAnimationStatusChanged);
if (_currentTween.begin != _currentTween.end) {
controller.forward();
}
}
void _onAnimationStatusChanged(AnimationStatus status) {
switch (status) {
case AnimationStatus.dismissed:
case AnimationStatus.forward:
case AnimationStatus.reverse:
break;
case AnimationStatus.completed:
if (widget.onEnd != null) {
widget.onEnd();
}
break;
}
}
@override
void forEachTween(TweenVisitor<dynamic> visitor) {
assert(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment