Home Introduction to Flutter UI Add Implicit Animations

Implicit Animations — Make Your Tiles Come Alive!

⏱️ 25-30 minutes 📊 Intermediate — The finishing touch! 📦 2 Projects included 🏷️ AnimatedContainer, Duration, Curves, Polish

🧒 Why Do My Tiles Change Instantly? (The Flip Book Analogy!)

📖

Right Now, Your Tiles "Snap" — Like Turning a Light Switch

When you submit a guess, the tiles change from white to green/yellow/gray instantly. It's functional, but it feels... abrupt. Like a light switch going from OFF to ON with nothing in between.

Implicit animations are like a dimmer switch — instead of snapping instantly, the color smoothly fades from old to new over a short time. It's the difference between a cheap toy and a polished, professional app!

🎯
By the end of this lesson:
  • ✅ You'll discover what "implicit animations" are
  • ✅ You'll convert your Container to AnimatedContainer
  • ✅ You'll control timing with Duration
  • ✅ You'll customize the feel with Curves
  • ✅ Your tiles will smoothly transition between colors!
🪄

Implicit vs Explicit — The "Just Tell Me What" Approach

Flutter has two ways to animate things. The easy one is implicit animations:

🪄

Implicit Animation

You just say WHAT you want. "I want the color to be green now." Flutter figures out the HOW — it smoothly animates from the old color to green automatically.

Example: AnimatedContainer, AnimatedOpacity

🎬

Explicit Animation

You control everything. You set up an AnimationController, define tweens, and manually control every frame. More power, but more work.

Example: AnimationController + Tween

For 90% of animations, implicit is all you need. Today you'll learn AnimatedContainer — it's just like Container, but with animation superpowers!

⏱️

Duration & Curves — The Speed and Feel of Your Animation

Two simple things control how your animation looks and feels:

⏱️

Duration

How LONG the animation takes. Duration(milliseconds: 500) = half a second. Shorter = snappy, longer = dramatic.

📈

Curve

How the animation SPEEDS UP or SLOWS DOWN. Linear = constant speed. BounceIn = springs in. EaseOut = starts fast, ends slow.

With just these two properties, you can create dozens of different animation feels — all without writing any complex animation code!

1 The Magic Change — Container → AnimatedContainer

Here's the beautiful thing: AnimatedContainer is a drop-in replacement for Container. All the same properties work — you just add animation timing!

Step 1.1 BEFORE: Your Current Tile (Instant Change)

Here's your current Tile widget using a regular Container:

Current Tile — Container (no animation)
return Container(           // ← Regular Container
    height: 60,
    width: 60,
    decoration: BoxDecoration(
        border: Border.all(color: Colors.grey.shade300),
        color: switch (hitType) {
            HitType.hit     => Colors.green,
            HitType.partial => Colors.yellow,
            HitType.miss    => Colors.grey,
            _               => Colors.white,
        },
    ),
    child: Center(
        child: Text(
            letter.toUpperCase(),
            style: Theme.of(context).textTheme.titleLarge,
        ),
    ),
);

When hitType changes, the color snaps instantly — white → green in 0 seconds. Functional, but jarring.

Step 1.2 AFTER: AnimatedContainer (Smooth Transition!)

Change just one word and add one line. That's it!

Updated Tile — AnimatedContainer ✨
return AnimatedContainer(  // ← CHANGED: "Animated" added!
    duration: Duration(milliseconds: 500),  // ← NEW: animation takes 0.5 seconds
    height: 60,
    width: 60,
    decoration: BoxDecoration(
        border: Border.all(color: Colors.grey.shade300),
        color: switch (hitType) {
            HitType.hit     => Colors.green,
            HitType.partial => Colors.yellow,
            HitType.miss    => Colors.grey,
            _               => Colors.white,
        },
    ),
    child: Center(
        child: Text(
            letter.toUpperCase(),
            style: Theme.of(context).textTheme.titleLarge,
        ),
    ),
);

That's literally it! Two changes:

  1. ContainerAnimatedContainer — The widget now has animation powers.
  2. duration: Duration(milliseconds: 500) — Tells Flutter: "Animate ALL property changes over half a second."

Everything else — height, width, decoration, child — stays exactly the same. AnimatedContainer knows how to smoothly transition between old and new values for all of them!

Try it now! Make these two changes, hot reload, and submit a guess. Watch the tiles — they now smoothly fade from white to green/yellow/gray over half a second. That's professional-level polish with just two lines of code!
🧠
How it works under the hood: When setState is called in GamePage, Flutter rebuilds the Tile with a new hitType. AnimatedContainer notices: "Oh! The color property changed from white to green. Let me animate that smoothly over 500ms!" It automatically calculates all the in-between colors and renders them frame by frame.

Step 1.3 Understanding Duration — Milliseconds, Seconds, and More

The Duration class is how Flutter measures time. Here are the different ways you can write it:

⏱️
Duration(milliseconds: 500) Half a second (most common)
Duration(seconds: 1) One full second (dramatic)
Duration(milliseconds: 250) Quarter second (snappy)
Duration(seconds: 2, milliseconds: 300) 2.3 seconds (you can combine units!)
Duration(minutes: 1) One minute (please don't use this for animations 😅)

Rule of thumb: Most UI animations should be between 200ms and 500ms. Faster than 200ms feels instant. Slower than 500ms feels sluggish.

2 Animation Curves — Change the "Feel" of Your Animation

By default, animations run at a constant speed (linear). But you can make them speed up, slow down, bounce, or spring using Curves!

Step 2.1 The Default: Linear (Constant Speed)

Without specifying a curve, Flutter uses Curves.linear — the animation moves at the same speed from start to finish:

Imagine a car driving at exactly 30mph the whole trip. 🚗💨 Boring but predictable.

Step 2.2 Add a Bounce Curve — Make It Fun!

Add just one more line to your AnimatedContainer:

Add curve to AnimatedContainer
return AnimatedContainer(
    duration: Duration(milliseconds: 500),
    curve: Curves.bounceIn,  // ← NEW! Makes the color "bounce" in
    height: 60,
    width: 60,
    decoration: BoxDecoration(/* ... */),
    child: Center(/* ... */),
);

Hot reload and submit a guess. The tiles now bounce into their new color — it feels playful and satisfying!

Step 2.3 Curve Cheat Sheet — Try These!

Here are the most useful curves. Try each one by replacing Curves.bounceIn:

📈

Curves.easeIn

Starts slow, then speeds up. Like a car accelerating from a stop.

📉

Curves.easeOut

Starts fast, then slows down. Like a car gently braking.

🔄

Curves.easeInOut

Slow start, fast middle, slow end. The most natural-feeling curve.

🏀

Curves.bounceOut

Bounces at the END of the animation. Like a ball settling down.

🫧

Curves.elasticIn

Stretches like a rubber band before snapping in. Dramatic!

Curves.fastOutSlowIn

Material Design standard. Fast start, very gradual end.

💡
Pro tip: Curves.easeInOut is the most professional choice for most UI animations. Curves.bounceIn adds personality — great for games! Avoid Curves.elasticIn for serious business apps — it's too playful.

3 What Else Can You Animate? — AnimatedContainer Superpowers

AnimatedContainer doesn't just animate colors — it animates almost every property a regular Container has!

Step 3.1 Everything AnimatedContainer Can Animate

Any of these properties, when changed, will smoothly animate to their new values:

📏

Size

width, height — Make a box grow or shrink smoothly.

🎨

Color

color in BoxDecoration — Fade between any two colors.

📐

Border Radius

borderRadius — Morph from square to circle!

↔️

Alignment

alignment — Slide a child from one position to another.

📦

Padding & Margin

padding, margin — Expand or contract spacing.

🌑

Shadow

boxShadow — Animate shadows appearing or deepening.

The magic: You don't write ANY animation code for these. Just change the property, and AnimatedContainer handles the smooth transition automatically!

Step 3.2 Other Implicit Animation Widgets

AnimatedContainer is just one of many implicit animation widgets. Here are others you'll use:

🧰
AnimatedOpacity Fade widgets in and out
AnimatedPadding Animate padding changes
AnimatedAlign Animate alignment position
AnimatedDefaultTextStyle Animate text style changes
AnimatedSwitcher Animate between two completely different widgets

They all follow the same pattern: Give them a new value, and they animate the transition automatically!

📝 What You Learned Today

You just added professional polish to your app with minimal code!

Discovered Implicit Animations

Implicit animations handle the "how" of animation — you just specify the new state and the widget animates automatically.

Used AnimatedContainer

Replaced Container with AnimatedContainer — tiles now smoothly transition between colors in half a second.

Customized with Curves

Added Curves.bounceIn for playful bouncing animations. Learned 6+ curve options for different feels.

Completed the Birdle Game!

Your Birdle game now has custom widgets, layouts, input, state management, AND smooth animations. 🎉

🧠 Test Yourself!

Let's check your animation knowledge:

Q1 What widget can you use to automatically animate changes to properties like color, size, and decoration?

Q2 What does the duration property control in an AnimatedContainer?

📦 Project 1: Animated Size Changer

Use AnimatedContainer to create a box that smoothly grows and shrinks when tapped!

Project 1 Beginner

Objective: Tap to Grow/Shrink a Box

📋 Requirements:

  1. Create a StatefulWidget called SizeAnimator
  2. Have a bool _isBig = false; state variable
  3. Use AnimatedContainer with:
    • duration: Duration(milliseconds: 300)
    • curve: Curves.easeInOut
    • Width: _isBig ? 200 : 100
    • Height: _isBig ? 200 : 100
    • Color: _isBig ? Colors.blue : Colors.red
    • borderRadius: BorderRadius.circular(_isBig ? 40 : 10)
  4. Wrap in GestureDetector — onTap, call setState(() { _isBig = !_isBig; })

🎯 Expected Output:

A colored square that smoothly animates between small/red/square-ish and big/blue/round when tapped. Size, color, AND border radius all animate simultaneously!

📦 Project 2: Animated Progress Bar

Build a smooth loading bar that fills up when tapped — great for understanding AnimatedContainer!

Project 2 Beginner

Objective: Build a Fill Animation

📋 Requirements:

  1. Create a StatefulWidget called ProgressBar
  2. Have a double _progress = 0.0; state variable
  3. Build a layout with:
    • A Text showing "Progress: X%" where X = (_progress * 100).toInt()
    • A Container (the track) with gray background, height: 30, full width
    • Inside the track, use FractionallySizedBox with widthFactor: _progress
    • Inside that, an AnimatedContainer with blue color that fills the fraction
  4. Add an ElevatedButton — each tap adds 0.1 to progress (up to 1.0)
  5. Use duration: Duration(milliseconds: 400) and curve: Curves.easeOut

🎯 Expected Output:

A progress bar that smoothly fills from 0% to 100% as you tap the button. The animated container slides the fill width smoothly!

💡
Hint: The AnimatedContainer wraps the blue fill area. Wrap the whole thing in a GestureDetector or just use a button below.

🚀 What's Next?

🎉 Congratulations! You've completed the "Introduction to Flutter UI" topic! Your Birdle game now has:

  • ✅ A complete 5×5 game grid with custom Tile widgets
  • ✅ A text input field with controller, focus management, and submit button
  • ✅ StatefulWidget with setState for dynamic UI updates
  • ✅ Smooth color animations with AnimatedContainer and curves

In the next topic, you'll dive into State Management — handling HTTP requests and more advanced state patterns!

🎉

Lesson Complete!

You added smooth, professional animations to your Birdle game with just two lines of code. This completes the Introduction to Flutter UI — you've built a fully functional, polished game!

Click the button above to track your progress!