Expert · Animations and performance · topic 35 of 50 · 30 min
Implicit animations
Explanation
Why animate?
Good motion explains what is happening: a card expanding shows where more details came from, a button shrinking shows it was pressed, a fade shows content was replaced. Small, quick animations make apps feel polished and help users follow changes. Too much motion distracts and drains battery, so animate with purpose.
Implicit means automatic
An implicit animation widget looks like a normal widget with two extra parameters: duration and curve. Whenever one of its properties changes (for example its width or colour), it animates from the old value to the new one by itself. You never manage timing yourself; you just change state.
class ExpandingCard extends StatefulWidget {
const ExpandingCard({super.key});
@override
State<ExpandingCard> createState() => _ExpandingCardState();
}
class _ExpandingCardState extends State<ExpandingCard> {
bool _open = false;
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () => setState(() => _open = !_open),
child: AnimatedContainer(
duration: const Duration(milliseconds: 300),
curve: Curves.easeInOut,
height: _open ? 200 : 80,
color: _open ? Colors.teal.shade100 : Colors.grey.shade200,
padding: const EdgeInsets.all(16),
child: const Text('Today\'s offer: 20% off on all sweets'),
),
);
}
}Behind the scenes, an implicit widget remembers the previous value of each property. When it rebuilds with a new value, it starts an internal animation that moves smoothly from the old to the new value over the duration. If the value changes again halfway, it simply continues from wherever it is towards the newest value, so rapid taps never cause jumps.
Because they are just widgets with state inside, implicit animations work with any state management approach: setState, Provider, Riverpod or Bloc. Whatever causes the rebuild with a new value also triggers the animation.
Common implicit widgets
| Widget | Animates |
|---|---|
| AnimatedContainer | Size, colour, padding, decoration, alignment |
| AnimatedOpacity | Fading in and out |
| AnimatedAlign / AnimatedPositioned | Moving a child to a new position |
| AnimatedPadding | Padding changes |
| AnimatedScale / AnimatedRotation | Scaling and rotating |
| AnimatedSwitcher | Replacing one child with another (fade by default) |
| TweenAnimationBuilder | Any value you define with a Tween |
Curves
A curve controls the speed over time. Curves.linear moves at a constant speed, which looks mechanical. Curves.easeInOut starts and ends slowly, which feels natural. Curves.easeOut is good for things entering the screen; Curves.elasticOut and bounceOut are playful, for special moments only. Typical durations are 150 to 400 milliseconds; longer feels slow.
AnimatedSwitcher
AnimatedSwitcher(
duration: const Duration(milliseconds: 250),
child: _isLoading
? const CircularProgressIndicator(key: ValueKey('loading'))
: Text('Rs $_total', key: const ValueKey('total')),
)TweenAnimationBuilder
TweenAnimationBuilder<double>(
tween: Tween(begin: 0, end: _progress), // animate up to the new progress value
duration: const Duration(milliseconds: 600),
builder: (context, value, child) => LinearProgressIndicator(value: value),
)Common mistakes
- Changing the value without setState: nothing animates because nothing rebuilds.
- AnimatedSwitcher between two widgets of the same type without different keys: no animation.
- Durations of one or two seconds for small UI changes: the app feels sluggish.
- Animating everything on a screen at once: distracting and expensive.
Need help?
Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.
Try:
Watch the lesson
Implicit animations · 1/6
Good motion explains changes. Keep animations short and purposeful.
Prefer a video by a teacher? Find free videos on “flutter implicit animations animatedcontainer animatedswitcher tweenanimationbuilder” on YouTube ↗
In real life: An add-to-cart button that reacts
A food app's "Add" button turns into a quantity stepper after the first tap. An AnimatedSwitcher cross-fades between the two, and an AnimatedContainer widens the button smoothly. The whole effect is a few lines of code and makes the action feel responsive.
AnimatedSwitcher(
duration: const Duration(milliseconds: 200),
child: _qty == 0
? FilledButton(key: const ValueKey('add'), onPressed: () => setState(() => _qty = 1), child: const Text('ADD'))
: Row(
key: const ValueKey('stepper'),
mainAxisSize: MainAxisSize.min,
children: [
IconButton(onPressed: () => setState(() => _qty--), icon: const Icon(Icons.remove)),
Text('$_qty'),
IconButton(onPressed: () => setState(() => _qty++), icon: const Icon(Icons.add)),
],
),
)Practice (0/3 done)
You change _open in an AnimatedContainer's height but nothing animates. What is missing?
Which curve usually feels most natural for UI changes?
Build a FAQ list where tapping a question expands its answer with AnimatedContainer or AnimatedSize, the arrow icon rotates with AnimatedRotation, and a "Show more" button fades extra questions in with AnimatedOpacity. Try three different curves and durations and pick the one that feels best.
Quick quiz
Read more (free)
Related help
Before this, learn
This topic builds on these. If something here feels new, open them first.
Related topics
- Explicit animationsAnimations and performance · same module
- Hero, page transitions and Lottie or RiveAnimations and performance · same module
- PerformanceAnimations and performance · same module
- Transitions and animationsFrontend Web Development · CSS layout and responsive design
- Widget testsResponsive design and testing
- What state is, and setStateState management
Questions people ask about this
Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.
What two parameters do implicit animation widgets need besides their normal properties?
Answer: duration (and optionally curve)
They handle the rest.
Which widget cross-fades between two different children?
Answer: AnimatedSwitcher
AnimatedSwitcher swaps children with a transition.
What is a typical duration for small UI animations?
Answer: 150 to 400 milliseconds
Short animations feel responsive.
What does a Tween describe?
Answer: The start and end values of an animation
Tween(begin, end).
Which properties are the smoothest to animate?Related
Answer: transform and opacity
transform and opacity do not trigger layout, so they stay smooth.
Which call loops an animation back and forth?Related
What is a Hero animation for?Related
Answer: Visually linking the same element across two screens during navigation
Shared element transition.
What does setState do?Related
Answer: Marks the widget as needing a rebuild after the state changes
Flutter then calls build again.
Pass the quiz (60% or more) or mark this topic as done when you are ready.
Your progress is saved on this device only.
Next steps
- 3 more topics in “Animations and performance” before its exam: Explicit animations, Hero, page transitions and Lottie or Rive, Performance.
- Module 9 exam: Animations and performance · 12 questions · 25 min, without help. 4 topics of this module still to finish first.
- Then the next module, Responsive design and testing. 50 topics left in the course before the final exam.