How to use hero widget in Flutter

The Hero widget in Flutter allows us to create smooth and beautiful animations when transitioning between two screens, where a widget's appearance is shared and animated. This is commonly used when a widget appears on one screen, and we want it to animate smoothly when transitioning to another screen. In this Answer, we will explore how we can implement hero animation.

Constructor and parameters

The Hero widget provides a constructor with various parameters to customize its behavior and layout.

const Hero({
  Key? key,
  required Object tag,
  CreateRectTween? createRectTween,
  HeroFlightShuttleBuilder? 
  flightShuttleBuilder,
  HeroPlaceholderBuilder? 
  placeholderBuilder,
  bool transitionOnUserGestures = false,
  required Widget child
})

Let's take a closer look at each parameter and its purpose:

  1. key: An optional key to identify the Hero widget.

  2. tag: A unique identifier connecting the source and destination Hero widgets.

  3. createRectTween: Function to create a custom animation trajectory.

  4. flightShuttleBuilder: Function to build a custom flying widget during animation.

  5. placeholderBuilder: Function to build a custom placeholder widget during animation.

  6. transitionOnUserGestures: Flag to indicate whether the Hero should animate on user gestures.

  7. child: The child widget is to be animated between screens.

Importing necessary libraries

Before using the Hero widget, make sure to import the required libraries in our Dart file:

import 'package:flutter/material.dart';

Define the Hero in the source screen

In the source screen, we need to wrap the widget that we want to animate with the Hero widget. The Hero widget requires a unique tag to identify the same widget in the destination screen. For example, if we want to animate an image, we can use the Hero widget as follows:

Hero(
tag: 'unique_tag_for_image', // Make sure this tag is unique for this particular widget.
child: Image.asset('path_to_your_image'),
)

Navigation to the destination screen

In the source screen, when we navigate to the destination screen, make sure to use Navigator.push and specify the destination screen with the MaterialPageRoute.

Navigator.push(
context,
MaterialPageRoute(
builder: (context) => DestinationScreen(),
),
);

Define the Hero in the destination screen

In the destination screen, we need to wrap the same widget with the Hero widget and use the same unique tag as defined in the source screen.

Hero(
tag: 'unique_tag_for_image', // Same tag as used in the source screen.
child: Image.asset('path_to_your_image'),
)

When we navigate to the destination screen, Flutter will automatically animate the widget between the source and destination screens using the Hero widget.

Code example

We get the following output by putting together the code explained above.

import 'package:flutter/material.dart';

/// Flutter code sample for [Hero].

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

class HeroApp extends StatelessWidget {

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

class HeroExample extends StatelessWidget {


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Hero Sample')),
      body: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          const SizedBox(height: 20.0),
          ListTile(
            leading: const Hero(
              tag: 'hero-rectangle',
              child: BoxWidget(size: Size(50.0, 50.0)),
            ),
            onTap: () => _gotoDetailsPage(context),
            title: const Text(
              'Tap on the icon to view hero animation transition.',
            ),
          ),
        ],
      ),
    );
  }

  void _gotoDetailsPage(BuildContext context) {
    Navigator.of(context).push(MaterialPageRoute<void>(
      builder: (BuildContext context) => Scaffold(
        appBar: AppBar(
          title: const Text('Second Page'),
        ),
        body: const Center(
          child: Hero(
            tag: 'hero-rectangle',
            child: BoxWidget(size: Size(200.0, 200.0)),
          ),
        ),
      ),
    ));
  }
}

class BoxWidget extends StatelessWidget {
  const BoxWidget({required this.size});

  final Size size;

  @override
  Widget build(BuildContext context) {
    return Container(
      width: size.width,
      height: size.height,
      color: Colors.blue,
    );
  }
}

Conclusion

The Hero widget enables seamless animations between screens. Wrap the widget with a unique tag in the source screen, then navigate to the destination screen. In the destination screen, use the same tag with Hero. Customize animation and appearance using optional parameters. This creates visually appealing transitions, enhancing the user experience.

Copyright ©2024 Educative, Inc. All rights reserved