Codementor Events

Flutter code recipe for Hero animation

Published Jan 31, 2019Last updated Feb 03, 2019
Flutter code recipe for Hero animation

Hero animation is a useful transition when items are listed with small icons. Tapping on icons can open in another page with enlarged icon widget.

Recipe: Hero animation to transition a list icon into an enlarged view on another detail page.

Focus Widget: Hero Widget

Hero(
    tag: 'hero-rectangle', 
    child: _blueDetailRectangle(),
),

Goal: Animate and enlarge list item icon using Hero widget. Tapping on a list item icon, opens up the item in another page with enlarged icon.
List item icon Detail page icon

Checkout Hero animation

Lets's go!

We need these things to accomplish our goal.

  1. List item along with Icon: I'll be using a rectangle widget for icon.

Icon widget in list item at first page:

    Widget _blueIconRectangle() {
        return Container(
          width: 50,
          height: 50,
          color: Colors.blue,
    );
  }

Hero widget in list:

Widget buildWidget(BuildContext context) {
    return Center(
        ...
              child: Hero(
                tag: 'hero-rectangle',
                child: _blueIconRectangle(),
              ),
              onTap: () => _gotoDetailsPage(context),

        ...
  }
  1. Enlarged icon to display on the second page.
  Widget _blueDetailRectangle() {
    return Container(
      width: 200,
      height: 200,
      color: Colors.blue,
    );
  }

Using enlarged icon in second page:

void _gotoDetailsPage(BuildContext context) {
    Navigator.of(context).push(MaterialPageRoute(
      builder: (ctx) => Scaffold(
            body: Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Hero(
                    tag: 'hero-rectangle',
                    child: _blueDetailRectangle(),
                  ),
                  Text(
                      'This is where you can see details about the list item tapped at previous page.'),
                ],
              ),
            ),
          ),
    ));
  }

Notice that Navigator.of(context).push() is needed to navigate to second page from first page
using the same tag.

  1. Making sure both widgets in step #1 and step #2 have same tag.
    Hero transitions use the same tag to identify the start and destination widgets.

Complete example code

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.green,
      ),
      home: HeroAnimationRecipe(title: 'Hero Animation'),
    );
  }
}

class HeroAnimationRecipe extends StatefulWidget {
  HeroAnimationRecipe({Key key, this.title}) : super(key: key);
  final String title;

  @override
  _HeroAnimationRecipeState createState() => _HeroAnimationRecipeState();
}

class _HeroAnimationRecipeState extends State<HeroAnimationRecipe> {

  Widget _blueIconRectangle() {
    return Container(
      width: 50,
      height: 50,
      color: Colors.blue,
    );
  }

  Widget _blueDetailRectangle() {
    return Container(
      width: 200,
      height: 200,
      color: Colors.blue,
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: buildDemoWidget(context),
    );
  }

  Widget buildDemoWidget(BuildContext context) {
    return Center(
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          SizedBox(
            height: 20.0,
          ),
          ListTile(
            leading: GestureDetector(
              child: Hero(
                tag: 'hero-rectangle',
                child: _blueIconRectangle(),
              ),
              onTap: () => _gotoDetailsPage(context),
            ),
            title: Text('Tap on the icon to view hero animation transition.'),
          ),
        ],
      ),
    );
  }

  void _gotoDetailsPage(BuildContext context) {
    Navigator.of(context).push(MaterialPageRoute(
      builder: (ctx) => Scaffold(
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Hero(
                tag: 'hero-rectangle',
                child: _blueDetailRectangle(),
              ),
              Text(
                  'This is where you can see details about the list item tapped at previous page.'),
            ],
          ),
        ),
      ),
    ));
  }
}

Source code repo:
Recipe source code is available here

References:

  1. Cookbook
  2. Reference
  3. Youtube video

Liked the article ? Please let me know in the comments below what other topics you would like me to write.

Discover and read more posts from Priyanka
get started