2
votes

I've got a simple AnimatedWidget with one child widget.

AnimatedContainer(
   duration: Duration(milliseconds: 2000),
   curve: Curves.bounceOut,
   decoration: BoxDecoration(
      color: Colors.purple,
   ),
   child: FlutterLogo(
     size: _boxSize,
   ),
),

where _boxSize is being animated like so:

void _startAnimation() => setState(() {
    _boxSize *= 1.7;
  });

AnimatedContainer is not working for child widgets, however. You need to change direct properties of AnimatedContainer for the animation to work.

This is in compliance with documentation:

The [AnimatedContainer] will automatically animate between the old 
and new values of properties when they change using the provided curve 
and duration. Properties that are null are not animated. 
Its child and descendants are not animated.

What is the equivalent of AnimatedContainer which is ALSO ABLE to animate its children?

2
Did you find solution?user7856586

2 Answers

4
votes

There are few widgets which will animate the child. You can swap the new flutter logo widget with preferred size using AnimatedSwitcher Widget.

  1. AnimatedSwitcher - This widget will swap the child widget with a new widget.
  2. AnimatedPositioned - It'll change the position of the child from the stack widget whenever the given position changes.
  3. AnimatedAlign - Animated version of align which will change the alignment of the child whenever the given alignment changes.
  4. AnimatedCrossFade - It fades between two children and animate itself between their sizes.
1
votes

There is no magic widget which would simply recursively animate all children. But I think what you want is an implicitly animated widget. ie. you change the constructor parameters of a widget, and as it changes it animates from one value to the next.

The easiest way is probably the ImplicitlyAnimatedWidget with a AnimatedWidgetBaseState. So for your example to animate a boxSize attribute this could look like:

class AnimatedFlutterLogo extends ImplicitlyAnimatedWidget {
  const AnimatedFlutterLogo({Key key, @required this.boxSize, @required Duration duration})
      : super(key: key, duration: duration);

  final double boxSize;

  @override
  ImplicitlyAnimatedWidgetState<ImplicitlyAnimatedWidget> createState() => _AnimatedFlutterLogoState();
}

class _AnimatedFlutterLogoState extends AnimatedWidgetBaseState<AnimatedFlutterLogo> {
  Tween<double> _boxSize;

  @override
  void forEachTween(visitor) {
    _boxSize = visitor(_boxSize, widget.boxSize, (dynamic value) => Tween<double>(begin: value));
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      child: FlutterLogo(
        size: _boxSize?.evaluate(animation),
      ),
    );
  }
}

which is imho already pretty concise, the only real boilerplate is basically the forEachTween(visitor) method which has to create Tween objects for all properties you'd like to animate.