Rotating container indefinitely

Issue

I would like to rotate an Image indefinitely.

This container is one of the widget within the stack and would like this to be rotating continuously non stop.

final AnimationController animation = AnimationController(
  duration: const Duration(milliseconds: 1800),
  vsync: const NonStopVSync(),
)..repeat();

final Tween tween = Tween(begin: 0.0, end: math.pi);

var square = Container(
  width: 100,
  height: 100,
  transform: Matrix4.identity(),
  color: Colors.amber,
);

...

class Foo extends State<Bar> {
    ...


    animation.addListener((){
       square.transform = Matrix4.rotationZ(tween.evaluate(animation));
    });

    Widget build(BuildContext context) {
        return Stack(
           children: [
              ...
              Center(
                 child: square
              )
           ]
        )
    }
}

and I get this error: 'transform' can't be used as a setter because it's final. (assignment_to_final at [digital_clock] lib/digital_clock.dart:139)

How would I do what I’m trying to do?

Solution

Try something like this:

class InfiniteAnimation extends StatefulWidget {
  final Widget child;
  final int durationInSeconds;

  InfiniteAnimation({@required this.child, this.durationInSeconds = 2,});

  @override
  _InfiniteAnimationState createState() => _InfiniteAnimationState();
}

class _InfiniteAnimationState extends State<InfiniteAnimation>
    with SingleTickerProviderStateMixin {
  AnimationController animationController;
  Animation<double> animation;
​
  @override
  void initState() {
    super.initState();
    animationController = AnimationController(
      vsync: this,
      duration: Duration(seconds: widget.durationInSeconds),
    );
    animation = Tween<double>(
      begin: 0,
      end: 12.5664, // 2Radians (360 degrees)
    ).animate(animationController);
​
    animationController.forward();
​
    animation.addStatusListener((status) {
      if (status == AnimationStatus.completed) {
        animationController.repeat();
      }
    });
  }
​
  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      animation: animationController,
      builder: (context, child) => Transform.rotate(
        angle: animation.value,
        child: widget.child,
      ),
    );
  }

  @override
  void dispose() {
    animationController?.dispose();

    super.dispose();
  }
}

You basically need to create a StatefulWidget that mixes in (with keyword) the SingleTickerProviderStateMixin, provide an AnimationController, start the animation, then when the animation completes, repeat.

The AnimationBuilder is a better way of telling the widget to update on every frame without having to listen to the animationController and call setState explicitly.

You can use it like this:

InfiniteAnimation(
  durationInSeconds: 2, // this is the default value
  child: Icon(
    Icons.expand_more,
    size: 50.0,
    color: Colors.white,
  ),
)

Answered By – SupposedlySam

Answer Checked By – Marilyn (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *