AnimatedSwitcher in Flutter: Crafting Polished State Transitions with Ease
How to use AnimatedSwitcher for effortless fade, scale, slide, and custom transition animations whenever child widgets or state values change.
Published on • November 1, 2026
AI Assistant

Creating custom animations with AnimationController, Tween, and explicit listeners can feel verbose when all you need is a smooth visual transition between two states. For switching between an empty view, a loading spinner, error text, or counter values, AnimatedSwitcher is one of the most powerful implicit animation widgets in Flutter (docs.flutter.dev).
In this article, we explore how AnimatedSwitcher works, why keys are essential, and how to craft custom transition builders.
The Magic of AnimatedSwitcher
AnimatedSwitcher watches its single child. Whenever the child widget changes, it automatically animates the previous child out while animating the new child in.
AnimatedSwitcher(
duration: const Duration(milliseconds: 350),
child: isLoading
? const CircularProgressIndicator(key: ValueKey('loading'))
: Text('User Profile Loaded', key: const ValueKey('loaded')),
)
The Rule of Keys: Why ValueKey is Required
Because Flutter widgets are lightweight configuration structs, Flutter’s element tree checks Widget.canUpdate(oldWidget, newWidget). If both the old and new children share the exact same runtime type (for example, switching between two Text widgets with different copy), Flutter will simply update the existing widget in place without triggering an animation!
By giving each child an explicit ValueKey, you inform Flutter that the widget identity has changed, immediately triggering the enter/exit animation.
Customizing Transitions with transitionBuilder
By default, AnimatedSwitcher performs a simple FadeTransition. You can customize this completely using transitionBuilder:
AnimatedSwitcher(
duration: const Duration(milliseconds: 400),
transitionBuilder: (Widget child, Animation<double> animation) {
// Combine scale and slide transitions
return ScaleTransition(
scale: animation,
child: FadeTransition(
opacity: animation,
child: child,
),
);
},
child: Text(
'Score: $currentScore',
key: ValueKey<int>(currentScore),
style: Theme.of(context).textTheme.headlineMedium,
),
)
Advanced Customization: layoutBuilder
If transitioning widgets have differing intrinsic sizes, AnimatedSwitcher uses a Stack by default to display the outgoing and incoming children concurrently during the animation. You can supply a custom layoutBuilder to align children or wrap them in an AnimatedSize widget for fluid geometric reshaping.
AnimatedSwitcher delivers production-grade, delightful micro-interactions with minimal lines of code.