0
0
FlutterHow-ToBeginner · 3 min read

How to Create Animation in Flutter: Simple Guide

To create animation in Flutter, use AnimationController to control the animation timing and AnimatedBuilder or AnimatedWidget to rebuild UI during animation. Initialize the controller in a StatefulWidget, define animation properties, and start the animation with controller.forward().
📐

Syntax

Flutter animations typically use AnimationController to manage animation timing and AnimatedBuilder to rebuild widgets when the animation value changes.

Key parts:

  • AnimationController(vsync, duration): Controls animation progress.
  • Animation: Defines the animation value (e.g., tween).
  • AnimatedBuilder: Rebuilds UI on animation updates.
  • vsync: Prevents offscreen animations from consuming resources.
dart
class MyAnimationWidget extends StatefulWidget {
  @override
  _MyAnimationWidgetState createState() => _MyAnimationWidgetState();
}

class _MyAnimationWidgetState extends State<MyAnimationWidget> with SingleTickerProviderStateMixin {
  late AnimationController controller;

  @override
  void initState() {
    super.initState();
    controller = AnimationController(vsync: this, duration: const Duration(seconds: 2));
    controller.forward();
  }

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

  @override
  Widget build(BuildContext context) {
    return Container();
  }
}
💻

Example

This example shows a simple animation that changes the size of a blue square from 0 to 200 pixels over 2 seconds.

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

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(home: AnimationExample());
  }
}

class AnimationExample extends StatefulWidget {
  const AnimationExample({super.key});

  @override
  State<AnimationExample> createState() => _AnimationExampleState();
}

class _AnimationExampleState extends State<AnimationExample> with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<double> _animation;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(vsync: this, duration: const Duration(seconds: 2));
    _animation = Tween<double>(begin: 0, end: 200).animate(_controller);
    _controller.forward();
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Flutter Animation Example')),
      body: Center(
        child: AnimatedBuilder(
          animation: _animation,
          builder: (context, child) {
            return Container(
              width: _animation.value,
              height: _animation.value,
              color: Colors.blue,
            );
          },
        ),
      ),
    );
  }
}
Output
A blue square grows smoothly from 0 to 200 pixels in width and height over 2 seconds in the center of the screen.
⚠️

Common Pitfalls

Common mistakes when creating animations in Flutter include:

  • Not disposing the AnimationController, which causes memory leaks.
  • Forgetting to add with SingleTickerProviderStateMixin to the state class, which is needed for vsync.
  • Not calling controller.forward() or controller.repeat() to start the animation.
  • Using setState() unnecessarily instead of AnimatedBuilder or AnimatedWidget for efficient rebuilds.
dart
/* Wrong: Missing dispose and vsync */
class WrongAnimation extends StatefulWidget {
  @override
  _WrongAnimationState createState() => _WrongAnimationState();
}

class _WrongAnimationState extends State<WrongAnimation> {
  late AnimationController controller;

  @override
  void initState() {
    super.initState();
    controller = AnimationController(vsync: null, duration: const Duration(seconds: 1)); // Missing vsync
    controller.forward();
  }

  @override
  Widget build(BuildContext context) {
    return Container();
  }
}

/* Right: Proper dispose and vsync */
class RightAnimation extends StatefulWidget {
  @override
  _RightAnimationState createState() => _RightAnimationState();
}

class _RightAnimationState extends State<RightAnimation> with SingleTickerProviderStateMixin {
  late AnimationController controller;

  @override
  void initState() {
    super.initState();
    controller = AnimationController(vsync: this, duration: const Duration(seconds: 1));
    controller.forward();
  }

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

  @override
  Widget build(BuildContext context) {
    return Container();
  }
}
📊

Quick Reference

Animation basics cheat sheet:

Class/MethodPurpose
AnimationControllerControls animation timing and progress
TweenDefines value range for animation
AnimatedBuilderRebuilds UI when animation changes
vsyncOptimizes animation resource usage
controller.forward()Starts animation forward
controller.dispose()Frees resources when done
Class/MethodPurpose
AnimationControllerControls animation timing and progress
TweenDefines value range for animation
AnimatedBuilderRebuilds UI when animation changes
vsyncOptimizes animation resource usage
controller.forward()Starts animation forward
controller.dispose()Frees resources when done

Key Takeaways

Use AnimationController with vsync to manage animation timing efficiently.
Wrap animated widgets with AnimatedBuilder to rebuild only when animation changes.
Always dispose AnimationController in the dispose() method to avoid memory leaks.
Start animations by calling controller.forward() or controller.repeat().
Use Tween to define the range of animated values.