How to add Hero animations to my ListView in Flutter?

Viewed 2023

I have a ListView that has cards as shown below. I am trying to animate the card to open in a bigger size upon being pressed.

I have already achieved this for a single card however I can not understand how to do this for a ListView. Upon adding the Hero tag on the ListView elements, I get the following error:

There are multiple heroes that share the same tag within a subtree.

This is the animation.

This is the code for the animation:

The first Page:

  Widget build(BuildContext context) {
    return new Scaffold(
      body: Hero(
          tag: 'flutterLogo',
          child: GestureDetector(
            onTap: () => Navigator.push(context,
                MaterialPageRoute(builder: (context) => AnimatedPage())),
            child: Card(
              elevation: 4.0,
              shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.circular(12.0),
              ),
              child: Container(
                height: 180,
                width: 300,
                color: Colors.blue,
              ),
            ),
          )),
    );
  }

The Second Page:

  Widget build(BuildContext context) {
    return new Scaffold(
      body: Stack(
        children: <Widget>[
          Hero(
            tag: 'flutterLogo',
            child: Padding(
              padding: const EdgeInsets.only(top: 20.0),
              child: Card(
                elevation: 4.0,
                color: Colors.red,
                shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(12.0),
                ),
                child: Container(
                  height: 200,
                  width: 300,
                  child: Center(child: Text('Hello')),
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }

And this is the code for my ListView:

 SliverList(
        delegate: SliverChildBuilderDelegate(
          (BuildContext context, int index) {
            return Hero(
              tag: 'flutterLogo',
              child: Padding(
                padding: const EdgeInsets.only(top: 10.0, bottom: 10),
                child: GestureDetector(
                  onTap: () {
                    Navigator.push(context,
                        MaterialPageRoute(builder: (context) => PaymentPage()));
                  },
                  child: Card(
                    elevation: 4.0,
                    shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(12.0),
                    ),
                    child: Container(
                      height: 180,
                      width: 150,
                    ),
                  ),
                ),
              ),
            );
          },
          childCount: 4,
        ),
      ),

And this is what the list looks like: enter image description here

I am trying to open the same second page as shown in the Animation, after clicking on the card in the List.

1 Answers

Hero Tags should be different, so in your SliverList change your tag to this:

tag: 'flutterLogo${index}',

and pass the tag to your second page, like this(in case its a StatefulWidget):

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

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

and then instead of using a simple tag in your second page use something like this:

tag: widget.heroTag,
Related