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:
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:
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:
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:
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 toAlignment.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
: TheTickerProvider
for this widget.Clip clipBehavior
: How to clip the content. Defaults toClip.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.