Skip to content
Boring Doc
Official documentation (snapshot)doc

Animate a widget across screens

How to animate a widget from one screen to another

Source last updated Oct 21, 2026 · last synchronized 3 weeks ago · commit b3045439b7c0 · read on docs.flutter.dev

This is a rendered snapshot of the official page as stored by Boring Doc for provenance and search. Site-specific components (embedded demos, DartPad, images with relative paths) may not render; use the official page for the full experience. Content © The Flutter Authors, CC BY 3.0.

It's often helpful to guide users through an app as they navigate from screen to screen. A common technique to lead users through an app is to animate a widget from one screen to the next. This creates a visual anchor connecting the two screens.

Use the Hero widget to animate a widget from one screen to the next. This recipe uses the following steps:

  1. Create two screens showing the same image.
  2. Add a Hero widget to the first screen.
  3. Add a Hero widget to the second screen.

1. Create two screens showing the same image

In this example, display the same image on both screens. Animate the image from the first screen to the second screen when the user taps the image. For now, create the visual structure; handle animations in the next steps.

Navigate to a new screen and back and Handle taps recipes.

import 'package:flutter/material.dart';

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

@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('Main Screen')), body: GestureDetector( onTap: () { Navigator.push( context, MaterialPageRoute( builder: (context) { return const DetailScreen(); }, ), ); }, child: Image.network('https://picsum.photos/250?image=9'), ), ); } }

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

@override Widget build(BuildContext context) { return Scaffold( body: GestureDetector( onTap: () { Navigator.pop(context); }, child: Center( child: Image.network('https://picsum.photos/250?image=9'), ), ), ); } }


## 2. Add a `Hero` widget to the first screen

To connect the two screens together with an animation, wrap
the `Image` widget on both screens in a `Hero` widget.
The `Hero` widget requires two arguments:

`tag`
: An object that identifies the `Hero`.
  It must be the same on both screens.

`child`
: The widget to animate across screens.


RegEx removes the first "child" property name and removed the trailing comma at the end


```dart
Hero(
  tag: 'imageHero',
  child: Image.network('https://picsum.photos/250?image=9'),
)

3. Add a Hero widget to the second screen

To complete the connection with the first screen, wrap the Image on the second screen with a Hero widget that has the same tag as the Hero in the first screen.

After applying the Hero widget to the second screen, the animation between screens just works.

RegEx removes the first "child" property name and removed the trailing comma at the end

Hero(
  tag: 'imageHero',
  child: Image.network('https://picsum.photos/250?image=9'),
)

As a best practice, create a reusable widget instead of repeating code. This example uses identical code for both widgets, for simplicity.

import 'package:flutter/material.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(title: 'Transition Demo', home: MainScreen());
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Main Screen')),
      body: GestureDetector(
        onTap: () {
          Navigator.push(
            context,
            MaterialPageRoute<void>(
              builder: (context) {
                return const DetailScreen();
              },
            ),
          );
        },
        child: Hero(
          tag: 'imageHero',
          child: Image.network('https://picsum.photos/250?image=9'),
        ),
      ),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: GestureDetector(
        onTap: () {
          Navigator.pop(context);
        },
        child: Center(
          child: Hero(
            tag: 'imageHero',
            child: Image.network('https://picsum.photos/250?image=9'),
          ),
        ),
      ),
    );
  }
}
Was this useful?

Content from flutter/website, © The Flutter Authors, used under the Creative Commons Attribution 3.0 License; code samples under the BSD License.