Flutter is a popular open-source UI software development toolkit by Google, used to build natively compiled applications for mobile, web, and desktop from a single codebase. One of the key aspects of creating interactive user interfaces in Flutter is animations. Animations add life to your UI, making it more visually appealing and interactive. In Flutter, animations can be categorized into implicit and explicit Animations. In this Answer, we will be discussing explicit animations in detail.
Explicit animations in Flutter are animations that developers control explicitly by specifying the animation behavior and properties. These animations require developers to explicitly define the animation values, such as starting and ending points, and manage the animation lifecycle themselves.
Therefore, explicit animations provide greater flexibility and control compared to implicit animations, making them suitable for complex and custom animation scenarios.
Note: If you want to learn about implicit animations in Flutter, go here.
Animation controller: The AnimationController
class controls the animation's lifecycle. It allows you to specify the duration, start and stop the animation, and control the animation's behavior using curves.
Animation: The Animation
class represents the current state of an animation. It holds the intermediate values that the animation has reached during its execution. These values can be mapped to the properties of UI elements to achieve smooth animations.
Tween: The Tween
class helps in mapping the range of the animation values to the desired property values. It defines how the intermediate animation values should be interpolated to produce the final output.
import 'package:flutter/material.dart'; void main() => runApp(ExplicitAnimationApp()); class ExplicitAnimationApp extends StatefulWidget { @override _ExplicitAnimationAppState createState() => _ExplicitAnimationAppState(); } class _ExplicitAnimationAppState extends State<ExplicitAnimationApp> with SingleTickerProviderStateMixin { AnimationController _controller; Animation<double> _opacityAnimation; @override void initState() { super.initState(); _controller = AnimationController( vsync: this, duration: Duration(seconds: 2), ); _controller.addStatusListener((status) { if (status == AnimationStatus.completed) { _controller.reverse(); } else if (status == AnimationStatus.dismissed) { _controller.forward(); } }); _opacityAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(_controller); _controller.forward(); } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar( title: Text('Explicit Animation Demo'), ), body: Center( child: AnimatedBuilder( animation: _controller, builder: (context, child) { return Opacity( opacity: _opacityAnimation.value, child: Text( 'Educative.io', style:TextStyle( color:Colors.black, fontSize:40, fontWeight:FontWeight.bold, ) , ), ); }, ), ), ), ); } }
Lines 5–7: A StatefulWidget
called the ExplicitAnimationApp
is defined. Stateful widgets are used when the state of a widget can change during the lifetime of the widget.
Lines 10–13: In the _ExplicitAnimationAppState class
, we use the SingleTickerProviderStateMixin
to act as a TickerProvider
for the animation. The AnimationController
instance _controller
is created with a duration of 2 seconds.
Lines 16–31: In the initState
method, we initialize the state of the widget. We create an AnimationController
instance _controller
, passing vsync: this
to provide the current _ExplicitAnimationAppState
as the TickerProvider
. We also set the animation's duration to 2 seconds.
Lines 22–28: The _controller.addStatusListener
method now listens for both the AnimationStatus.completed
and AnimationStatus.dismissed
. When the animation reaches the end, we reverse it, and when it reaches the start, we forward it again. This process creates a continuous animation that scales the Text up and then scales it back down repeatedly.
Lines 34–37: In the dispose
method, the _controller
is disposed to free up resources associated with the animation.
Lines 40–67: We use the AnimatedBuilder
widget to rebuild only the specific widget subtree that depends on the animation value. The Opacity
widget controls the transparency of its child based on the _opacityAnimation.value
, creating a pulsating effect on the blue Text
widget.
Free Resources