Flutter rebuild a TweenAnimationBuilder

Issue

I want to make a flipping animation with TweenAnimationBuilder, a container will flip over and change the color. I want to add a button when user click on it, the container will flip over again and change into another colour.

Here is my code:

import 'package:flutter/material.dart';
import 'dart:math';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  bool isBack = true;

  Color backColor = Colors.green;
  Color topColor = Colors.red;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              box(),
              SizedBox(height: 10),
              ElevatedButton(
                  style: ElevatedButton.styleFrom(
                    minimumSize: Size(25, 10),
                    elevation: 10,
                  ),
                  onPressed: () {
                    setState(() {
                      backColor = Colors.red;
                      topColor = Colors.blue;
                    });
                  },
                  child:
                      Text('change to blue', style: TextStyle(fontSize: 16))),
            ],
          ),
        ),
      ),
    );
  }

  Widget box() {
    print('building');
    return TweenAnimationBuilder(
        tween: Tween<double>(begin: 0, end: pi),
        duration: Duration(seconds: 1),
        builder: (BuildContext context, double value, _) {
          print(value);
          if (value >= (pi / 2)) {
            isBack = false;
          } else {
            isBack = true;
          }
          return (Transform(
            alignment: Alignment.center,
            transform: Matrix4.identity()
              ..setEntry(3, 2, 0.001)
              ..rotateY(value),
            child: Container(
                width: 100,
                height: 100,
                child: isBack
                    ? Container(
                        color: backColor,
                      )
                    : Transform(
                        alignment: Alignment.center,
                        transform: Matrix4.identity()
                          ..rotateY(
                              pi),
                        child: Container(
                          color: topColor,
                        ),
                      ) 
                ),
          ));
        });
  }
}

At the first build, the tween value will start from the beginning:

building
0
0
0
0.13080335172486462
0.19619246121668257
0.2180893620122034
...
3.141592653589793

but when I click on the button to change the color, it will not start again from the begin value, it just stays at 3.14:

building
3.141592653589793

Right now the button will only change the color of the container, but it will not flip again.

I suppose after the setstate function, the tween value will restart again at 0, why won’t it do so?
Can anybody explain it please?

Solution

All you need is an AnimationController and AnimatedBuilder to control the animation.

class _HomePageState extends State<HomePage>
    with SingleTickerProviderStateMixin {
  bool isBack = true;

  Color backColor = Colors.blue;
  Color topColor = Colors.red;
  late AnimationController _animationController;
  late Animation _rotationAnimation;
  @override
  void initState() {
    super.initState();
    _animationController =
        AnimationController(vsync: this, duration: const Duration(seconds: 1));

    _rotationAnimation =
        Tween<double>(begin: 0, end: pi).animate(_animationController);

     _animationController.forward();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              box(),
              SizedBox(height: 10),
              ElevatedButton(
                  style: ElevatedButton.styleFrom(
                    minimumSize: Size(25, 10),
                    elevation: 10,
                  ),
                  onPressed: () {
                    setState(() {
                      backColor = Colors.red;
                      topColor = Colors.blue;
                    });
                    // if (_animationController.isDismissed) {
                    //   _animationController.forward();
                    // } else if (_animationController.isCompleted) {
                    //   _animationController.reverse();
                    // }
                    _animationController.forward(from: 0.0);
                  },
                  child:
                      Text('change to blue', style: TextStyle(fontSize: 16))),
            ],
          ),
        ),
      ),
    );
  }

  Widget box() {
    return AnimatedBuilder(
        animation: _animationController,
        // tween: Tween<double>(begin: 0, end: pi),
        // duration: Duration(seconds: 1),
        builder: (_, __) {
          // print(value);
          if (_rotationAnimation.value >= (pi / 2)) {
            isBack = false;
          } else {
            isBack = true;
          }
          return Transform(
            alignment: Alignment.center,
            transform: Matrix4.identity()
              ..setEntry(3, 2, 0.001)
              ..rotateY(_rotationAnimation.value),
            child: Container(
              width: 100,
              height: 100,
              child: isBack
                  ? Container(
                      color: backColor,
                    )
                  : Transform(
                      alignment: Alignment.center,
                      transform: Matrix4.identity()..rotateY(pi),
                      child: Container(
                        color: topColor,
                      ),
                    ),
            ),
          );
        });
  }
}

Answered By – Watery Desert

Answer Checked By – David Marino (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published.