Built-In Explicit Animations

Abubakar Saddique
13 min readOct 17, 2023

--

What are Built In Explicit Animations ??

According to the official documentation

The Flutter SDK also provides built-in explicit animations, such as FadeTransition, SizeTransition, and SlideTransition.

These simple animations are triggered by setting a beginning and ending point.

Some of the control of the animation is given to the user or programmer

Let’s talk about the explicit built in animation in details with examples

Before starting the deep dive

Let me explain you some things

i ) Ticker Provider State Mixin :

The ticker provider state mixin is used to provide a new tick on every change in the animation

The ticker provider state mixin are of two types

i ) Single Ticker Provider State Mixin :

The single ticker provider state mixin is used with only one controller

If you are managing all of the animation on the screen with a single controller then use the single ticker provider state mixin

ii ) Ticker Provider State Mixin :

The ticker provider state mixin is used for more than one controller

If you are managing the animations on the screen with a more than one controller’s then use the ticker provider state mixin

i ) Animation Controller :

Animation controller is the controller for the animation .

It provides us the control on the animation about how and when to start , stop , dismiss , reverse the animation

According to the official documentation

An AnimationController linearly produces values that range from 0.0 to 1.0, during a given duration. The animation controller generates a new value whenever the device running your app is ready to display a new frame (typically, this rate is around 60 values per second).

Follow these steps to create an animation controller

i ) Declare the Animation Controller :

  late AnimationController _animationController;

Declare the animation controller using late

ii ) Initialize the Animation controller :

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

Initialize the animation controller in the initial state of the state of the state full life cycle

The animation controller provides us a lot of method’s that help’s us to control the animation that we should discuss later

. Duration :

The Duration property of the animation controller is used to duration of the animation

. Vsync :

vsync is used to sync the animation controller with the ticker provider

iii ) Dispose The Animation Controller :

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

Dispose the animation controller in the dispose method of the state of the state full life cycle

iii ) Tween :

Make a tween which will provide the value to the animation

The word tween derives from the “Between” which provides us the values between the range (starting and ending ) value

iv ) Animation :

i ) Declare the animation :

Declare the animation reference variable and initialize it later

ii ) Initialize the animation variable :

Initialize the animation variable using late in the initial state of the state of the state full widget

    _animation = tween.animate(_animationController);

Now let’s talk about how to perform these animation or how to use these properties

The transition’s are used to to perform the built in explicit animations

Transition” means the movement of things from one position to another

Let’s deep dive into the transition’s

i ) Rotation Transition :

The rotation transition is used to rotate the given child widget in clockwise direction

RotationTransition RotationTransition({
Key? key,
required Animation<double> turns,
Alignment alignment = Alignment.center,
FilterQuality? filterQuality,
Widget? child,
})

. Turns :

The turns property are used to set the number of the turns of the animation . One turn is used to rotate the widget to 360 degree

import 'package:flutter/material.dart';

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

@override
State<RotationTransitionDesign> createState() =>
_RotationTransitionDesignState();
}

class _RotationTransitionDesignState extends State<RotationTransitionDesign>
with SingleTickerProviderStateMixin {
late AnimationController _animationController;
late Animation<double> _animation;
Tween<double> tween = Tween<double>(begin: 0, end: 1);

@override
void initState() {
// TODO: implement initState
super.initState();
_animationController =
AnimationController(vsync: this, duration: const Duration(seconds: 2));
_animation = tween.animate(_animationController);
}

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

void rotateContainer() async {
await _animationController.forward();
_animationController.reverse();
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Rotated Transition Design"),
centerTitle: true,
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
RotationTransition(
turns: _animation,
child: Container(
width: 300,
height: 300,
color: Colors.purple,
),
)
],
),
),
floatingActionButton: FloatingActionButton(onPressed: rotateContainer),
);
}
}

On the click event of the floating action button . I rotate the container and then reverse it . mean’s first it start’s moving in clock wise direction then it will move back in anti clock wise direction

The forward method of the animation is used to start the animation for the first time

The reverse method of the animation controller is used to reverse the animation or start’s from the ending and end it on the starting point

For more information about the animation controller .

Kindly read it from the official documentation or you may get some knowledge from my article on animation controller

ii ) Scale Transition :

The scale transition is used to scale the given child widget or change the size of the given widget

ScaleTransition ScaleTransition({
Key? key,
required Animation<double> scale,
Alignment alignment = Alignment.center,
FilterQuality? filterQuality,
Widget? child,
})

The original scale of the scale of the widget is 1 . if the scale is increased to 2 then the widget will become double of it’s size

import 'package:flutter/material.dart';

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

@override
State<ScaleTransitionDesign> createState() => _ScaleTransitionDesignState();
}

class _ScaleTransitionDesignState extends State<ScaleTransitionDesign>
with SingleTickerProviderStateMixin {
late AnimationController _animationController;
late Animation<double> _animation;
Tween<double> tween = Tween<double>(begin: 1, end: 2);

@override
void initState() {
// TODO: implement initState
super.initState();
_animationController = AnimationController(
vsync: this, duration: const Duration(milliseconds: 600));
_animation = tween.animate(_animationController);
}

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

void scaleContainer() async {
await _animationController.forward();
_animationController.reverse();
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Scale Transition Design"),
centerTitle: true,
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
ScaleTransition(
scale: _animation,
child: Icon(
Icons.favorite,
color: Colors.red,
size: 350,
),
)
],
),
),
floatingActionButton: FloatingActionButton(onPressed: scaleContainer),
);
}
}

On the click event of the floating action button i change the scale of the icon of heart (favorite)

iii ) Align Transition :

The align transition animation is used to change the animation of the given widget

AlignTransition AlignTransition({
Key? key,
required Animation<AlignmentGeometry> alignment,
required Widget child,
double? widthFactor,
double? heightFactor,
})

The Alignment property is used to set the alignment of the given widget

The width and the height factor is used to set the width and the height of the given if it is not mentioned

import 'package:flutter/material.dart';

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

@override
State<AlignTransitionDesign> createState() => _AlignTransitionDesignState();
}

class _AlignTransitionDesignState extends State<AlignTransitionDesign>
with SingleTickerProviderStateMixin {
late AnimationController _animationController;
late Animation<Alignment> _animation;
Tween<Alignment> tween =
Tween<Alignment>(begin: Alignment.topLeft, end: Alignment.bottomRight);

@override
void initState() {
// TODO: implement initState
super.initState();
_animationController = AnimationController(
vsync: this, duration: const Duration(milliseconds: 600));
_animation = tween.animate(_animationController);
}

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

void changeContainerAlignment() async {
await _animationController.forward();
_animationController.reverse();
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Align Transition Design"),
centerTitle: true,
),
body: Center(
child: AlignTransition(
alignment: _animation,
child: Container(
width: 200,
height: 200,
color: Colors.purple,
)),
),
floatingActionButton:
FloatingActionButton(onPressed: changeContainerAlignment),
);
}
}

On the click event of the floating action button i change the alignment of the container from the top left to bottom right and then vice versa .

iv ) Decorated Box Transition :

Decorated box transition is used to set the decoration of the decorated box

This will animate the border radius , shadows , colors , and multiple things of the decorated box .

DecoratedBoxTransition DecoratedBoxTransition({
Key? key,
required Animation<Decoration> decoration,
DecorationPosition position = DecorationPosition.background,
required Widget child,
})

Box decoration is used to decorate pr animated the container’s decorated box

import 'package:flutter/material.dart';

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

@override
State<DecoratedBoxTransitionDesign> createState() =>
_DecoratedBoxTransitionDesignState();
}

class _DecoratedBoxTransitionDesignState
extends State<DecoratedBoxTransitionDesign>
with SingleTickerProviderStateMixin {
late AnimationController _animationController;
late Animation<Decoration> _animation;

DecorationTween decorationTween = DecorationTween(
begin: BoxDecoration(
borderRadius: BorderRadius.circular(70), color: Colors.amber),
end: BoxDecoration(
borderRadius: BorderRadius.circular(10), color: Colors.purple));

@override
void initState() {
// TODO: implement initState
super.initState();
_animationController = AnimationController(
vsync: this, duration: const Duration(milliseconds: 600));
_animation = decorationTween.animate(_animationController);
}

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

void changeContainerDecoration() async {
await _animationController.forward();
_animationController.reverse();
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Decorated Box Transition Design"),
centerTitle: true,
),
body: Center(
child: DecoratedBoxTransition(
decoration: _animation,
child: Container(
width: 800,
height: 800,
)),
),
floatingActionButton: FloatingActionButton(onPressed: changeContainerDecoration),
);
}
}

On the click event of the floating action button . I animate the decoration of the container

If you want’s more information about the decorated box of the container in detail’s

Kindly read it from the official documentation or you may get knowledge from my article on container widget in which i try to guide in detail about the decorated box

v ) Default Text Style Transition :

Default text style transition is used to animate the text by changing it’s text style

DefaultTextStyleTransition DefaultTextStyleTransition({
Key? key,
required Animation<TextStyle> style,
required Widget child,
TextAlign? textAlign,
bool softWrap = true,
TextOverflow overflow = TextOverflow.clip,
int? maxLines,
})

If you want’s more information about the text style kindly read it from the official documentation or you may also get information about the text style from my article on it

import 'package:flutter/material.dart';

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

@override
State<DefaultTextStyleTransitionDesign> createState() =>
_DefaultTextStyleTransitionDesignState();
}

class _DefaultTextStyleTransitionDesignState
extends State<DefaultTextStyleTransitionDesign>
with SingleTickerProviderStateMixin {
late AnimationController _animationController;
late Animation<TextStyle> _animation;
TextStyleTween tween = TextStyleTween(
begin: TextStyle(
color: Colors.pink,
fontStyle: FontStyle.italic,
fontSize: 50,
fontWeight: FontWeight.normal),
end: TextStyle(
color: Colors.purple,
fontSize: 100,
fontStyle: FontStyle.normal,
fontWeight: FontWeight.bold));

@override
void initState() {
// TODO: implement initState
super.initState();
_animationController =
AnimationController(vsync: this, duration: const Duration(seconds: 2));
_animation = tween.animate(_animationController);
}

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

void changeTextStyle() async {
await _animationController.forward();
_animationController.reverse();
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Default Text Style Transition Design"),
centerTitle: true,
),
body: Center(
child: DefaultTextStyleTransition(
style: _animation, child: Text("Hi Abubakar")),
),
floatingActionButton: FloatingActionButton(onPressed: changeTextStyle),
);
}
}

On the click event of the floating Action Button i will animate the text by changing it’s text style

vi ) Fade Transition :

Fade Transition is used to change the opacity or to animate the given widget using the fade in or fade out

FadeTransition FadeTransition({
Key? key,
required Animation<double> opacity,
bool alwaysIncludeSemantics = false,
Widget? child,
})

The opacity is used to set the fade value

The opacity of zero mean’s fully opaque or fully visible

The opacity of 1 mean’s fully transparent

import 'package:flutter/material.dart';

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

@override
State<FadeTransitionDesign> createState() => _FadeTransitionDesignState();
}

class _FadeTransitionDesignState extends State<FadeTransitionDesign>
with SingleTickerProviderStateMixin {
late AnimationController _animationController;
late Animation<double> _animation;

Tween<double> tween = Tween<double>(begin: 1, end: 0);

@override
void initState() {
// TODO: implement initState
super.initState();
_animationController =
AnimationController(vsync: this, duration: const Duration(seconds: 2));
_animation = tween.animate(_animationController);
}

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

void changeContainerOpacity() async {
await _animationController.forward();
_animationController.reverse();
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Fade Transition Design"),
centerTitle: true,
),
body: Center(
child: FadeTransition(
opacity: _animation,
child: Container(
width: 800,
height: 800,
color: Colors.amber,
)),
),
floatingActionButton: FloatingActionButton(onPressed: changeContainerOpacity),
);
}
}

On the click event of the floating action button . i will change the opacity of the given child container from 1 to 0 and then vice versa

vii ) Positioned Transition Animation :

The positioned transitioned animation is used to perform the animation by changing the position of the given child widget in the parent

PositionedTransition PositionedTransition({
Key? key,
required Animation<RelativeRect> rect,
required Widget child,
})

According to the official documentation

The positioned transitioned must be used inside the Stack Widget

Relative rect is used to set the positioned of the given child widget while animating it

If you wan’t more information about the positioned transition widget kindly read it from the official documentation or you may also get knowledge from my article on relative rect

According to the official documentation

An immutable 2D, axis-aligned, floating-point rectangle whose coordinates are given relative to another rectangle’s edges, known as the container. Since the dimensions of the rectangle are relative to those of the container, this class has no width and height members.

import 'package:flutter/material.dart';

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

@override
State<PositionedTransitionedDesign> createState() =>
_PositionedTransitionedDesignState();
}

class _PositionedTransitionedDesignState
extends State<PositionedTransitionedDesign>
with SingleTickerProviderStateMixin {
late AnimationController _animationController;
late Animation<RelativeRect> _animation;
RelativeRectTween relativeRectTween = RelativeRectTween(
begin: RelativeRect.fromSize(Rect.fromLTWH(0, 0, 200, 200), Size(10, 10)),
end: RelativeRect.fromSize(
Rect.fromLTWH(1500, 900, 200, 200), Size(20, 20)));

@override
void initState() {

super.initState();
_animationController = AnimationController(
vsync: this, duration: const Duration(milliseconds: 600));
_animation = relativeRectTween.animate(_animationController);
}

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

void changeContainerPosition() async {
await _animationController.forward();
_animationController.reverse();

// _animationController.repeat();
}

@override
Widget build(BuildContext context) {
var screenSize = MediaQuery.sizeOf(context);
var screenWidth = screenSize.width;
var screenHeight = screenSize.height;
var clientHeight = screenHeight - kToolbarHeight;
return Scaffold(
appBar: AppBar(
title: Text("Positioned Transition Design"),
centerTitle: true,
),
body: Container(
width: screenWidth,
height: clientHeight,
color: Colors.white,
child: Stack(
children: [
PositionedTransition(
rect: _animation,
child: Text(
"Abubakar",
style: TextStyle(
fontSize: 30,
color: Colors.amber,
fontWeight: FontWeight.bold),
)),
],
),
),
floatingActionButton: FloatingActionButton(onPressed: changeContainerPosition),
);
}
}

On the click event of the floating action button i will animate the given child container by changing the position of that widget inside the stack

viii ) Relative Positioned Transition :

The relative positioned transition is similar as the positioned transition but the only difference is that the

RelativePositionedTransition RelativePositionedTransition({
Key? key,
required Animation<Rect?> rect,
required Size size,
required Widget child,
})

Relative Rect is used in simple positioned transition and the only rect is used to set the positioned of the given child widget in the stack for relative positioned transition

import 'package:flutter/material.dart';

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

@override
State<RelativePositionedTransitionedDesign> createState() =>
_RelativePositionedTransitionedDesignState();
}

class _RelativePositionedTransitionedDesignState
extends State<RelativePositionedTransitionedDesign>
with SingleTickerProviderStateMixin {
late AnimationController _animationController;
late Animation<Rect?> _animation;
RectTween relativeRectTween = RectTween(
begin: Rect.fromLTWH(0, 0, 200, 200),
end: Rect.fromLTWH(1500, 900, 200, 200));

@override
void initState() {
// TODO: implement initState
super.initState();
_animationController = AnimationController(
vsync: this, duration: const Duration(milliseconds: 600));
_animation = relativeRectTween.animate(_animationController);
}

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

void changeContainerPosition() async {
await _animationController.forward();
_animationController.reverse();

// _animationController.repeat();
}

@override
Widget build(BuildContext context) {
var screenSize = MediaQuery.sizeOf(context);
var screenWidth = screenSize.width;
var screenHeight = screenSize.height;
var clientHeight = screenHeight - kToolbarHeight;
return Scaffold(
appBar: AppBar(
title: Text("Relative Positioned Transition Design"),
centerTitle: true,
),
body: Container(
width: screenWidth,
height: clientHeight,
color: Colors.white,
child: Stack(
children: [
RelativePositionedTransition(
rect: _animation,
child: Text("Abubakar"),
size: Size(200, 200),
),
],
),
),
floatingActionButton: FloatingActionButton(onPressed: changeContainerPosition),
);
}
}

If you wan’t more information about the Rect kindly read it from the official documentation or you may also get knowledge from my article on it

On the click event of the floating action button i change the position of the given child text

ix ) Size Transition :

The size transition is used to animate the given child by cropping the size of the given child widget

According to the official documentation

Animates its own size and clips and aligns its child.

SizeTransition acts as a ClipRect that animates either its width or its height, depending upon the value of axis. The alignment of the child along the axis is specified by the axis Alignment.

SizeTransition SizeTransition({
Key? key,
Axis axis = Axis.vertical,
required Animation<double> sizeFactor,
double axisAlignment = 0.0,
Widget? child,
})

Axis is sued to set whether the animation will be perform by clipping the given child in vertical direction or horizontal direction

size factor is used to set the size that how should it will be clipped

import 'package:flutter/material.dart';

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

@override
State<SizeTransitionDesign> createState() => _SizeTransitionDesignState();
}

class _SizeTransitionDesignState extends State<SizeTransitionDesign>
with SingleTickerProviderStateMixin {
late AnimationController _animationController;
late Animation<double> _animation;
Tween<double> tween = Tween<double>(begin: 0, end: 1);

@override
void initState() {
// TODO: implement initState
super.initState();
_animationController = AnimationController(
vsync: this, duration: const Duration(milliseconds: 600));
_animation = tween.animate(_animationController);
}

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

void startAnimation() async {
await _animationController.forward();
_animationController.reverse();
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Size Transition Design"),
centerTitle: true,
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizeTransition(
sizeFactor: _animation,
child: Icon(
Icons.favorite,
size: 500,
color: Colors.red,
)),
],
),
),
floatingActionButton: FloatingActionButton(onPressed: startAnimation),
);
}
}

On the click event of the floating action button i start’s the animation .

The animation start’s from clipping the icon of heart until the center and then vice versa

x ) Slide Transition :

The slide transition is used to slide the given child in either horizontal or vertical direction

 SlideTransition SlideTransition({
Key? key,
required Animation<Offset> position,
bool transformHitTests = true,
TextDirection? textDirection,
Widget? child,
})

The offset’s are used to slide the given child in the parent

The offset are the point’s on the cartesian plane . Offset (x, y)

According to the official documentation

For example, an Offset with a dx of 0.25 will result in a horizontal translation of one quarter the width of the child.

The value of 1 will move full of the length along the given side

import 'package:flutter/material.dart';

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

@override
State<SlideTransitionDesign> createState() => _SlideTransitionDesignState();
}

class _SlideTransitionDesignState extends State<SlideTransitionDesign>
with SingleTickerProviderStateMixin {
late AnimationController _animationController;
late Animation<Offset> _animation;
// According to the official documentation
// For example, an Offset with a dx of 0.25 will result in a horizontal translation of one quarter the width of the child.
Tween<Offset> tween = Tween<Offset>(begin: Offset(-2, -2), end: Offset(2, 2));

@override
void initState() {
// TODO: implement initState
super.initState();
_animationController = AnimationController(
vsync: this, duration: const Duration(seconds: 2));
_animation = tween.animate(_animationController);

}

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

void slideContainer() async {
await _animationController.forward();
_animationController.reverse();
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Slide Transition Design"),
centerTitle: true,
),
body: Center(
child: SlideTransition(
position: _animation,
child: Container(
width: 200,
height: 200,
color: Colors.pink,
),
),
),
floatingActionButton: FloatingActionButton(onPressed: slideContainer),
);
}
}

On the click event of the floating action button . i will slide the given child container in both horizontal and vertical directions

That’s all for the built in explicit animation

I hope you learned a lot of new things 📚

Thanks for reading 😊

--

--