Let’s start with the Advanced Animations in Flutter:
Animations play a vital role in enhancing the user experience in mobile applications, and Flutter offers a powerful toolkit to create smooth and interactive animations. In this blog, we’ll explore advanced animation techniques in Flutter, focusing on Hero Animations, Animation Controllers, and Tweens. By the end of this guide, you’ll be equipped to create stunning animations that will make your Flutter apps more engaging.

Understanding Hero Animations
A Hero Animation is a transition animation that happens between two screens, typically for shared elements. It’s a simple yet effective way to provide visual continuity and smooth transitions. This type of animation is great for shifting elements like images, buttons, or other UI components between screens.
How Hero Animations Work:
Hero Animations allow widgets to “fly” from one screen to another. You can think of it as a shared element transition between the two screens, where the widget morphs smoothly from one screen’s layout to the other.


Implementing a Hero Animation:
Here’s a quick example to get started:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: FirstScreen(),
);
}
}
class FirstScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('First Screen')),
body: Center(
child: GestureDetector(
onTap: () {
Navigator.push(context, MaterialPageRoute(
builder: (context) => SecondScreen(),
));
},
child: Hero(
tag: 'hero-example',
child: Container(
width: 100,
height: 100,
color: Colors.blue,
),
),
),
),
);
}
}
class SecondScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Second Screen')),
body: Center(
child: Hero(
tag: 'hero-example',
child: Container(
width: 300,
height: 300,
color: Colors.blue,
),
),
),
);
}
}
Explanation:
- Hero Widget: The Hero widget wraps the UI element you want to animate between two screens. The
tag
property must be the same on both screens, which tells Flutter that the widget is the same across transitions. - GestureDetector: We use this to trigger the navigation when the user taps on the widget.
When you tap the blue square, it smoothly grows in size and transitions from the first screen to the second.
Animation Controllers: Taking Full Control
While Hero Animations are perfect for transitions between screens, sometimes you need more precise control over how animations are timed and executed. This is where Animation Controllers come into play.
What is an Animation Controller?
An AnimationController in Flutter is like the conductor of an orchestra. It controls how long the animation lasts, when it starts, when it ends, and even how it should reverse.
Basic Example of Animation Controller:
class AnimationControllerExample extends StatefulWidget {
@override
_AnimationControllerExampleState createState() => _AnimationControllerExampleState();
}
class _AnimationControllerExampleState extends State<AnimationControllerExample> with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<double> _animation;
@override
void initState() {
super.initState();
_controller = AnimationController(
duration: const Duration(seconds: 2),
vsync: this,
);
_animation = Tween<double>(begin: 0, end: 300).animate(_controller);
_controller.forward();
}
@override
Widget build(BuildContext context) {
return Center(
child: AnimatedBuilder(
animation: _animation,
builder: (context, child) {
return Container(
width: _animation.value,
height: 100,
color: Colors.green,
);
},
),
);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
}
Explanation:
AnimationController
is initialized with a duration of 2 seconds and the vsync property to avoid unnecessary animations.- We use
Tween
to interpolate the values for the width of the container from 0 to 300. AnimatedBuilder
is used to rebuild the widget whenever the animation value changes.
You can see how the AnimationController gives you fine control over the duration and timing of the animation. You can even pause, reverse, or repeat the animation.
Tweens: Transitioning Between Values
A Tween in Flutter is used to interpolate values between two endpoints. This can be anything from size, position, opacity, or even colors.
Basic Tween Example:
We’ve already seen how to use a simple Tween to animate the width of a container, but Tweens can animate multiple properties simultaneously. Here’s how we can animate both the width and color of a container:
class MultiTweenExample extends StatefulWidget {
@override
_MultiTweenExampleState createState() => _MultiTweenExampleState();
}
class _MultiTweenExampleState extends State<MultiTweenExample> with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<double> _widthAnimation;
late Animation<Color?> _colorAnimation;
@override
void initState() {
super.initState();
_controller = AnimationController(
duration: const Duration(seconds: 2),
vsync: this,
);
_widthAnimation = Tween<double>(begin: 100, end: 300).animate(_controller);
_colorAnimation = ColorTween(begin: Colors.red, end: Colors.blue).animate(_controller);
_controller.forward();
}
@override
Widget build(BuildContext context) {
return Center(
child: Container(
width: _widthAnimation.value,
height: 100,
color: _colorAnimation.value,
),
);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
}
Explanation:
Tween<double>
is used for the width, interpolating between 100 and 300.ColorTween
interpolates between red and blue for the container’s color.- Both animations are controlled by the same AnimationController, making them run simultaneously.
This gives you incredible flexibility when animating multiple properties at once.
Combining Hero Animations with Controllers and Tweens
Now that we’ve covered Hero Animations, Animation Controllers, and Tweens, let’s combine them into a more complex animation. Imagine we have a button that transitions to a new screen using a Hero Animation, and during the transition, the button grows in size and changes color.
This will combine everything we’ve learned so far into one cohesive animation.
class FirstScreen extends StatelessWidget {
const FirstScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('First Screen'),
),
body: Center(
child: GestureDetector(
onTap: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => SecondScreen()));
},
child: Hero(
tag: 'hero-button',
child: AnimatedButton(
height: 50,
width: 150,
),
)),
),
);
}
}
class SecondScreen extends StatelessWidget {
const SecondScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Second Screen'),
),
body: Center(
child: Hero(
tag: 'hero-button',
child: AnimatedButton(height: 75, width: 250),
),
),
);
}
}
class AnimatedButton extends StatefulWidget {
final double height;
final double width;
const AnimatedButton({super.key, required this.height, required this.width});
@override
State<AnimatedButton> createState() => _AnimatedButtonState();
}
class _AnimatedButtonState extends State<AnimatedButton>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<double> _sizeAnimation;
late Animation<Color?> _colorAnimation;
@override
void initState() {
super.initState();
_controller =
AnimationController(duration: const Duration(seconds: 2), vsync: this);
_sizeAnimation = Tween<double>(begin: widget.width, end: widget.width + 100)
.animate(CurvedAnimation(
parent: _controller,
curve: Curves.easeInOut,
));
_colorAnimation = ColorTween(begin: Colors.blue, end: Colors.green)
.animate(CurvedAnimation(
parent: _controller,
curve: Curves.easeInOut,
));
_controller.forward();
}
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _controller,
builder: (context, child) {
return Container(
width: _sizeAnimation.value,
height: widget.height,
decoration: BoxDecoration(
color: _colorAnimation.value,
borderRadius: BorderRadius.circular(12),
),
child: const Center(
child: Text(
'Animated Button',
style: TextStyle(color: Colors.white, fontSize: 16),
),
),
);
});
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
}
Best Practices for Animations
- Performance Considerations: Always use
vsync
to optimize animation performance, especially when working with Animation Controllers. - Subtlety is Key: Don’t overuse animations. While they’re fun to create, too many animations can overwhelm users.
- Test on Different Devices: Ensure that your animations run smoothly on lower-end devices, as animations can be resource-intensive.
Conclusion
In this guide, we’ve covered some of the most powerful animation tools in Flutter: Hero Animations, Animation Controllers, and Tweens. You now have the knowledge to create smooth transitions, control animation timings, and interpolate between values, making your Flutter apps more engaging and professional.
Feel free to try these examples in your projects and let me know how they work for you. If you found this helpful, share it with others and keep experimenting with new animations in Flutter!
Explore Other Flutter Topics…
- Introduction to Flutter and Dart
- Why choose Flutter
- Installing Flutter On Your Windows Mac And Linux System
- Your first Flutter app
- Flutter project structure
- Building blocks of Flutter
- Stateful vs. Stateless Widgets Explained
- Flutter layout system
- Flutter text widget
- Creating Buttons in Flutter: ElevatedButton, TextButton, and IconButton
- Handling User Input with Flutter Forms
- Container class in Flutter
- Flutter Navigation
- Flutter – Pass Data One Screen To Another Screen
- Managing Device Orientation in Flutter
- Stateful widget lifecycle in Flutter
- Future of Flutter
- Flutter Themes
- Flutter Animations
- Flutter AppBar Customization
- ListView in Flutter
- Flutter GridView
- Flutter Expanded Widget
- Flutter BottomNavigation Bar
- Floating Action Button
- Drawer Widgets in Flutter
- Form Validation in Flutter
- Flutter TextField
- Adding AdMob ads to a Flutter app
- Building Flutter Web & Desktop Applications
- What is Async and Await in Flutter
- HTTP requests in Flutter
- Parsing JSON in Flutter
- Tinder-Style Swipe Cards in Flutter
- Flutter Tic Tac Toe Game Tutorial
- Flutter Login UI Tutorial
- Flutter Card Widget Tutorial
- Flutter music player app tutorial
- Flutter introduction screens
- Shared Preferences in Flutter
- SQLite Database in Flutter
- Firebase Authentication in Flutter
- Firebase Firestore in Flutter
- Push Notifications in Flutter
- Handling File Uploads in Flutter
- Responsive Design in Flutter
- Provider in Flutter
- Riverpod in Flutter
- Flutter BLoC Pattern Tutorial