Flutter - Using AnimatedSize Widget Examples

This tutorial is about how to use the AnimatedSize widget in Flutter.

In Flutter, AnimatedSize is a widget that animates its size to match the size of its child. In this tutorial, I am going to explain how to use the widget with some examples.

Using AnimatedSize

To use AnimatedSize, below is the constructor that you need to call.

  const AnimatedSize({
    Key? key,
    Widget? child,
    AlignmentGeometry alignment = Alignment.center,
    Curve curve = Curves.linear,
    required Duration duration,
    Duration? reverseDuration,
    required TickerProvider vsync,
    Clip clipBehavior = Clip.hardEdge,
  })

There are two required arguments: vsync and duration. Below I am going to explain how to provide the values for the required and non-required arguments.

In this tutorial, we are going to animate a simple widget whose size depends on a state variable _size.

  Widget _buildChild() {
    return Container(
      width: _size,
      height: _size,
      // color: Colors.teal,
      decoration: BoxDecoration(
          image: DecorationImage(
              image: NetworkImage(
                  'https://www.woolha.com/media/2021/05/woolha-250x250.jpg'
              )
          )
      ),
    );
  }

  Widget _buildAnimatedSize() {
    return Container(
      decoration: BoxDecoration(
        border: Border.all(),
      ),
      child: AnimatedSize(
        // vsync: ...,
        // duration: ...,
        // other arguments
        child: _buildChild(),
      ),
    );
  }

Below the AnimatedSize widget, there's a button for switching the value of the _size between small value and big value.

  Column(
    mainAxisAlignment: MainAxisAlignment.center,
    children: [
      _buildAnimatedSize(),
      ElevatedButton(
        child: Text('Change Size'),
        onPressed: () {
          setState(() {
            _size = _size == 150 ? 250 : 150;
          });
        },
      )
    ],
  )

Set TickerProvider

As you can see in the constructor, you are required to pass an argument named vsync whose type is TickerProvider. In order to obtain the value for the argument, you need to use a Stateful widget and the respective State class has to use TickerProviderStateMixin.

  class _AnimatedSizeExampleState extends State<AnimatedSizeExample>
    with TickerProviderStateMixin {

    }

By doing so, it becomes possible to pass this keyword as the value for vsync argument.

  Widget _buildAnimatedSize() {
    return Container(
      decoration: BoxDecoration(
        border: Border.all(),
      ),
      child: AnimatedSize(
        vsync: this,
        // duration: ...,
        // other arguments
        child: _buildChild(),
      ),
    );
  }

Set Duration

The animation duration can be set by passing a Duration value as the duration argument. Below is a basic example which only passes the required arguments and the child argument.

  Widget _buildAnimatedSize() {
    return Container(
      decoration: BoxDecoration(
        border: Border.all(),
      ),
      child: AnimatedSize(
        vsync: this,
        duration: const Duration(seconds: 2),
        // other arguments
        child: _buildChild(),
      ),
    );
  }

Output:

Flutter - AnimatedSize

Set Alignment

You can control how to align the child within the parent during the animation when the size of the parent is not the same as the child's size yet. It can be done by passing an AlignmentGeometry value as the alignment argument. You can use the predefined constant (e.g. center, topLeft) or create a custom alignment using the Alignment constructor.

  const Alignment(double x, double y)

The x and y values are used to set the horizontal and vertical alignments respectively. An x value of -1.0 means the child's left edge is aligned with the parent's left edge. An x value of 1.0 means the child's right edge is aligned with the parent's right edge. For the vertical alignment, a y value of -1.0 means the child's top edge is aligned with the parent's top edge. A y value of 1.0 means the child's bottom edge is aligned with the parent's bottom edge. An x or y value of 0.0 means the child's center is aligned with the center of the parent in the respective axis.

  Widget _buildAnimatedSize() {
    return Container(
      decoration: BoxDecoration(
        border: Border.all(),
      ),
      child: AnimatedSize(
        vsync: this,
        duration: const Duration(seconds: 2),
        alignment: Alignment(-0.75, -0.75),
        // other arguments
        child: _buildChild(),
      ),
    );
  }

Output:

Flutter - AnimatedSize - Alignment

Set Curve

Just like other Flutter animations, it allows you to set the curve of the animation. You can do it by passing a Curve value as the curve argument.

  Widget _buildAnimatedSize() {
    return Container(
      decoration: BoxDecoration(
        border: Border.all(),
      ),
      child: AnimatedSize(
        vsync: this,
        duration: const Duration(seconds: 2),
        curve: Curves.easeInCubic,
        // other arguments
        child: _buildChild(),
      ),
    );
  }

Output:

Flutter - AnimatedSize - Curve

Animating Child

The AnimatedSize is used to animate a parent widget to match the size of its child. It doesn't animate the child widget. If what you need is animating the size change of a widget, one of the alternatives is using the AnimatedContainer widget. The AnimatedContainer is a Container that can animate its child when any property changes.

  Widget _buildSizeAnimationWithAnimatedContainer() {
    return AnimatedContainer(
      width: _size,
      height: _size,
      color: Colors.teal,
      duration: const Duration(seconds: 2),
      child: _buildChild(),
    );
  }

Output:

Flutter - AnimatedContainer - Size

AnimatedSize - Parameters

  • Key? key: The widget's key, used to control how a widget is replaced with another widget.
  • Widget? child: The widget under this widget in the tree.
  • AlignmentGeometry alignment: The alignment of the child within the parent during the animation when the size of the parent is not the same as the child's size yet. Defaults to Alignment.center.
  • Curve curve: The animation curve when sizing to match the child's size.
  • required Duration duration: The animation duration when sizing to match the child's size.
  • Duration? reverseDuration: The animation duration when sizing to match the child's size in reverse.
  • required TickerProvider vsync: The TickerProvider for this widget.
  • Clip clipBehavior: How to clip the content. Defaults to Clip.hardEdge.

Full Code

  import 'package:flutter/material.dart';
  import 'package:flutter/rendering.dart';
  
  void main() => runApp(MyApp());
  
  class MyApp extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
      return MaterialApp(
        title: 'Woolha.com Flutter Tutorial',
        home: AnimatedSizeExample(),
      );
    }
  }
  
  class AnimatedSizeExample extends StatefulWidget {
    @override
    _AnimatedSizeExampleState createState() =>
        new _AnimatedSizeExampleState();
  }
  
  class _AnimatedSizeExampleState extends State<AnimatedSizeExample>
      with TickerProviderStateMixin {
  
    double _size = 150;
  
    Widget _buildChild() {
      return Container(
        width: _size,
        height: _size,
        // color: Colors.teal,
        decoration: BoxDecoration(
          image: DecorationImage(
            image: NetworkImage(
              'https://www.woolha.com/media/2021/05/woolha-250x250.jpg'
            ),
          ),
        ),
      );
    }
  
    Widget _buildAnimatedSize() {
      return Container(
        decoration: BoxDecoration(
          border: Border.all(),
        ),
        child: AnimatedSize(
          vsync: this,
          duration: const Duration(seconds: 2),
          // alignment: Alignment(-0.75, -0.75),
          // curve: Curves.easeInCubic,
          child: _buildChild(),
        ),
      );
    }
  
    Widget _buildSizeAnimationWithAnimatedContainer() {
      return AnimatedContainer(
        width: _size,
        height: _size,
        color: Colors.teal,
        duration: const Duration(seconds: 2),
        child: _buildChild(),
      );
    }
  
    @override
    Widget build(BuildContext context) {
      return Scaffold(
        appBar: AppBar(
          title: Text('Woolha.com Flutter Tutorial'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              _buildAnimatedSize(),
              // _buildSizeAnimationWithAnimatedContainer(),
              ElevatedButton(
                child: Text('Change Size'),
                onPressed: () {
                  setState(() {
                    _size = _size == 150 ? 250 : 150;
                  });
                },
              )
            ],
          ),
        ),
      );
    }
  }

Summary

AnimatedSize can be used if you want to animate the size of a parent widget when the size of the child widget changes. The usage is quite simple, you are required to pass the TickerProvider and Duration arguments. Keep in mind that it doesn't animate the child widget.

You can also read about:

  • AnimatedCrossFade, which is used to create fade transition effects between two widgets.
  • AnimatedAlign, a widget for creating animation when the alignment of a widget changes.
  • AnimatedPadding, a widget for creating animation when the padding of a widget changes.
  • AnimatedSwitcher, a widget for creating animation when switching between two widgets.
  • AnimatedOpacity, a widget for creating animation when the opacity of a widget changes.
  • AnimatedContainer, a widget that starts an animation when the value of a property changes.