Can you use Flutter's transform class to animate scale?

hello_friend picture hello_friend · Mar 25, 2019 · Viewed 8.3k times · Source

I'm trying to animate two square containers so that when they are tapped they are animated to scale. I see all these transform class examples online that show animation of a widget however when I use the transform class the scale just jumps from its initial value to its final value.

My end goal is to animate a container to 'bounce' every time it is tapped like what you can do with bounce.js in web development. To understand what I mean you can go to http://bouncejs.com, click 'select preset' in the upper left corner, select jelly from the drop down menu and click 'play animation'.

Can this be done with the transform class?

Here is my code:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

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

class MyHomePage extends StatefulWidget {
  _MyHomePageState createState() => _MyHomePageState();
}

var squareScaleA = 0.5;
var squareScaleB = 0.5;

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Bounce Example"),
      ),
      body: Stack(
        children: <Widget>[
          Container(
            width: 300.0,
            height: 150.0,
            color: Colors.yellowAccent,
          ),
          Column(
            children: <Widget>[
              Row(
                children: <Widget>[
                  GestureDetector(
                    onTap: () {
                      setState(() {
                        squareScaleA = 1.0;
                      });
                    },
                    child: Transform.scale(
                      scale: squareScaleA,
                      child: Container(
                        width: 150.0,
                        height: 150.0,
                        color: Colors.green,
                      ),
                    ),
                  ),
                  GestureDetector(
                    onTap: () {
                      setState(() {
                        squareScaleB = 1.0;
                      });
                    },
                    child: Transform.scale(
                      scale: squareScaleB,
                      child: Container(
                        width: 150.0,
                        height: 150.0,
                        color: Colors.blue,
                      ),
                    ),
                  ),
                ],
              ),
            ],
          ),
        ],
      ),
    );
  }
}

Thanks in advance for any help!

Answer

diegoveloper picture diegoveloper · Mar 25, 2019

You need to use Animations, you can start using AnimationController it's very simple , I fixed your sample :

    class _MyHomePageState extends State<TestingNewWidget>
        with TickerProviderStateMixin {
      var squareScaleA = 0.5;
      var squareScaleB = 0.5;
      AnimationController _controllerA;
      AnimationController _controllerB;

      @override
      void initState() {
        _controllerA = AnimationController(
            vsync: this,
            lowerBound: 0.5,
            upperBound: 1.0,
            duration: Duration(seconds: 1));
        _controllerA.addListener(() {
          setState(() {
            squareScaleA = _controllerA.value;
          });
        });
        _controllerB = AnimationController(
            vsync: this,
            lowerBound: 0.5,
            upperBound: 1.0,
            duration: Duration(seconds: 1));
        _controllerB.addListener(() {
          setState(() {
            squareScaleB = _controllerB.value;
          });
        });
        super.initState();
      }

      @override
      void dispose() {
        _controllerA.dispose();
        _controllerB.dispose();
        super.dispose();
      }

      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text("Bounce Example"),
          ),
          body: Stack(
            children: <Widget>[
              Container(
                width: 300.0,
                height: 150.0,
                color: Colors.yellowAccent,
              ),
              Column(
                children: <Widget>[
                  Row(
                    children: <Widget>[
                      GestureDetector(
                        onTap: () {
                          if (_controllerA.isCompleted) {
                            _controllerA.reverse();
                          } else {
                            _controllerA.forward(from: 0.0);
                          }
                        },
                        child: Transform.scale(
                          scale: squareScaleA,
                          child: Container(
                            width: 150.0,
                            height: 150.0,
                            color: Colors.green,
                          ),
                        ),
                      ),
                      GestureDetector(
                        onTap: () {
                          if (_controllerB.isCompleted) {
                            _controllerB.reverse();
                          } else {
                            _controllerB.forward(from: 0.0);
                          }
                        },
                        child: Transform.scale(
                          scale: squareScaleB,
                          child: Container(
                            width: 150.0,
                            height: 150.0,
                            color: Colors.blue,
                          ),
                        ),
                      ),
                    ],
                  ),
                ],
              ),
            ],
          ),
        );
      }
    }

Also you can read more about animation here: https://flutter.dev/docs/development/ui/animations