0
0
FlutterHow-ToBeginner · 4 min read

How to Use Hero Animation in Flutter for Smooth Transitions

Use the Hero widget in Flutter by wrapping the shared widget on both source and destination screens with the same tag. Flutter automatically animates the transition between these widgets when navigating between routes.
📐

Syntax

The Hero widget requires a tag property that uniquely identifies the shared element. Wrap the widget you want to animate with Hero(tag: 'uniqueTag', child: YourWidget) on both the source and destination pages.

When you navigate between pages, Flutter matches the tag and animates the widget smoothly.

dart
Hero(
  tag: 'hero-tag',
  child: Image.asset('assets/picture.png'),
)
Output
A widget wrapped in Hero with tag 'hero-tag' ready for animation between screens.
💻

Example

This example shows two screens: a list with small images and a detail page with a larger image. Both images are wrapped in Hero widgets with the same tag. Tapping the image navigates to the detail page with a smooth hero animation.

dart
import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: const ListPage(),
    );
  }
}

class ListPage extends StatelessWidget {
  const ListPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Hero Animation Example')),
      body: Center(
        child: GestureDetector(
          onTap: () {
            Navigator.push(
              context,
              MaterialPageRoute(builder: (_) => const DetailPage()),
            );
          },
          child: Hero(
            tag: 'hero-image',
            child: Image.network(
              'https://flutter.dev/assets/homepage/carousel/slide_1-bg-4e2fcef0f6b3b6f9a9f1a4a2a6a7f7a4e7f7a4e7f7a4e7f7a4e7f7a4e7f7a4e7.png',
              width: 100,
            ),
          ),
        ),
      ),
    );
  }
}

class DetailPage extends StatelessWidget {
  const DetailPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Detail Page')),
      body: Center(
        child: Hero(
          tag: 'hero-image',
          child: Image.network(
            'https://flutter.dev/assets/homepage/carousel/slide_1-bg-4e2fcef0f6b3b6f9a9f1a4a2a6a7f7a4e7f7a4e7f7a4e7f7a4e7f7a4e7f7a4e7.png',
            width: 300,
          ),
        ),
      ),
    );
  }
}
Output
App with a small image on the first screen that smoothly expands to a larger image on the detail screen when tapped.
⚠️

Common Pitfalls

  • Tag mismatch: The tag must be exactly the same on both widgets, or the animation won't work.
  • Different widget types: The widgets wrapped by Hero should be visually similar for a smooth animation.
  • Missing Hero on destination: Forgetting to wrap the destination widget with Hero causes no animation.
  • Large widget rebuilds: Avoid rebuilding the hero widget unnecessarily during animation to prevent glitches.
dart
/* Wrong: Different tags */
Hero(tag: 'tag1', child: Image.asset('img1.png'))

/* Right: Same tags */
Hero(tag: 'sharedTag', child: Image.asset('img1.png'))
📊

Quick Reference

  • Wrap shared widgets with Hero and use the same tag.
  • Use Navigator.push to trigger the animation.
  • Ensure widgets look similar for smooth transition.
  • Hero animations work best with images or icons.

Key Takeaways

Wrap widgets with Hero using the same tag on both screens to enable animation.
Use Navigator.push to navigate and trigger the hero animation automatically.
Ensure the hero widgets are visually similar for a smooth transition effect.
Avoid tag mismatches and missing Hero widgets on destination screens.
Hero animations are ideal for images and icons shared between screens.