I have an animation and can't understand one thing in this code

class _MyStatefulWidgetState extends State<MyStatefulWidget>
    with TickerProviderStateMixin {
  late final AnimationController _controller = AnimationController(
    duration: const Duration(seconds: 3),
    vsync: this,
  )..forward();

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    Size size = MediaQuery.of(context).size;
    return Material(
      child: Stack(
        children: [
      AnimatedBuilder(
                animation: _controller,
                builder: (context, child) {
                  return AnimatedPositioned(
                    top: ((size.height) * _controller.value) + 100,
                    duration: Duration(milliseconds: 500),
                    curve: Curves.fastOutSlowIn,
                    left: 0,
                    child: Container(
                      height: 250,
                      width: size.width * 0.6,
                      color: Colors.red,
                    ),
                  );
                },
              ),
          ]
        )
      );
  }
}

This code creates a container and animates its position. The thing I am unable to understand is I have specified a duration (500 milliseconds) in AnimatedPositioned and have specified 3 seconds as duration for _controller

  1. Why the box animates in 3 sec and not in 500 milliseconds
  2. The animation does not follow the curve initially (i.e it moves linearly and then after some time it decides to follow the curve)

I am still learning animations so it can be a silly doubt but I really can't understand it. If someone can explain whats going on with relevant code examples it would be really appreciated


Solution 1: Mahesh Jamdade

Look at your code you have specified duration to AnimatedPositioned widget.basically AnimationController interpolates from 0-1 in the duration specified which is 3 secs in your example.With each smallest change in value of animationController the animatedBuilder is getting rebuilt and simulatenously we also see there is change in the value of top of AnimatedPositioned widget but by the time it starts animating animatedBuilder is getting rebuilt again.This scenario continues until AnimationController completes its animation(i.e interpolation from 0-1 for 3 secs). Post the animationController completes AnimatedPositioned widget starts animating its top value based on the lastValue(at the end of 3 secs) to currentValue It animates using the duration and curve specified to it.

To summarize you will see two animations happening first one(one with AnimationController) takes 3 secs and the second animation(using AnimatedPositioned) takes 500 milliseconds. The second animation always tries to complete its animation but since its wrapped in AnimatedBuilder it ends up finishing its animation at the end of 3 secs.

The way AnimatedPositioned works is for each change in Property of this widget on rebuilding widgets (e.g by setState) you see the widget animating from its oldValue to new Value within the duration specified.

e.g you have specified top: ((size.height) * _controller.value) + 100,
when the value of top is changed e.g you assign it to lets say 100 by doing setState then you will see the curves and duration taking effect and the widget animating vertically from the original value to 100.

AnimatedContainer(),AnimatedPositioned() etc this type of widgets work without the AnimationController and in that case you would need to provide duration to these widgets.

I would recommend taking a look at The AnimatedPositioned Widget's example here, which basically explains the example that I gave above