Search code examples
flutterflutter-animation

flutter_animate animating a widget when button is pressed


i am using flutter_animate package and i would like to animate my text when the button below is pressed. I found a way to do this but the text is getting animated when the widget is built. Maybe im doing something wrong when animating the text:

class MainApp extends StatefulWidget {
  MainApp({super.key});

  @override
  State<MainApp> createState() => _MainAppState();
}

class _MainAppState extends State<MainApp> with TickerProviderStateMixin {
  late AnimationController _animationCtrl;

  @override
  Widget build(BuildContext context) {
    _animationCtrl = AnimationController(vsync: this);

    return MaterialApp(
      home: Scaffold(
        body: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Center(
              child: animateText(_animationCtrl),
            ),
            FloatingActionButton(onPressed: () {
              _animationCtrl.forward();
              setState(() {});
            })
          ],
        ),
      ),
    );
  }

  Animate animateText(AnimationController animationCtrl) {
    return Animate(
      child: Text("text")
          .animate(controller: animationCtrl)
          .moveX(end: 300, duration: 700.ms),
    );
  }
}


Solution

  • First, you should not initiate the controller inside the build method. Move it to initState:

    class _MainAppState extends State<MainApp> with TickerProviderStateMixin {
      late AnimationController _animationCtrl;
    
      @override
      void initState() {
        super.initState();
        _animationCtrl = AnimationController(vsync: this); // (1) Add this
      }
    
      // (3) Add the disposal too
      @override
      void dispose() {
        _animationCtrl.dispose();
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        // (2) Remove _animationCtrl instantiation line
    
        return MaterialApp(
    

    After that, you should specify autoPlay: false inside animate so that it doesn't play automatically:

    Text("text")
        .animate(controller: animationCtrl, autoPlay: false)
    

    That should fix the issue.


    Additionally, when you use .animate you don't need to wrap the widget with Animate. So just return the Text directly:

    Animate animateText(AnimationController animationCtrl) {
      return Text("text")
          .animate(controller: animationCtrl, autoPlay: false)
          .moveX(end: 300, duration: 700.ms);
    }
    

    setState is not needed when forwarding an animation. You can remove it:

    FloatingActionButton(onPressed: () {
      _animationCtrl.forward();
      // Remove the setState line
    })