Pink Room Blog
Engineering

Making Flutter Mobile Apps Shine with 3 Easy UI Effects — Part III

Hero Animations

This blog post is the last one of a series where we will talk about the Hero animation in Flutter.

Hero Animation

If you’ve used an app with a stunning UI, chances are you’ve seen an animation like the one created by the Hero widget.

In our use case, we want the music player users to view the audio cover in detail by tapping on it. To do this, we’ll start by creating a widget that displays the cover in full screen.

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

  @override
  Widget build(BuildContext context) => GestureDetector(
    onTap: () => Navigator.pop(context),
    child: BackdropFilter(
      filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5),
      child: Scaffold(
        backgroundColor: Colors.black.withAlpha(150),
        body: Center(
          child: Hero(
            tag: Constants.coverPath,
            child: Image.asset(Constants.coverPath, fit: BoxFit.cover),
          ),
        ),
      ),
    ),
  );
}

This widget is fairly simple. We draw the cover image in the center of the screen, add a semi-transparent black background to keep a hint of the previous screen visible, and apply a blur effect — because, well, it looks cool 😎. Moreover, when we tap on the screen, we navigate back.

As you might have noticed, our image is wrapped in a Hero widget. This will tell Flutter that when navigating to this screen, if there’s another Hero widget with the same tag, it should fly between the two screens. This is called a shared element animation.

Now, let’s update our code, where we use the cover image.

GestureDetector(
  onTap: _showCoverInFullScreen,
  child: Hero(
    tag: Constants.coverPath,
    child: MusicCover(),
  ),
);

void _showCoverInFullScreen() => Navigator.of(context).push(
  PageRouteBuilder(
    opaque: false,
    pageBuilder: (context, _, __) => FullScreenMusicCover(),
  ),
);

Again, this is quite simple. We just wrap our MusicCover widget in a Hero widget using the same tag as before, and navigate to the FullScreenMusicCover when the user taps it. That’s it! You now have a smooth and beautiful animation with almost no effort.

Check the full source code here.

Before ending this blog post, we have one more thing. If you tried out the music player app, you might have noticed a micro animation when the play/pause button switches states. This subtle animation is implemented using code similar to the example below

IconButton(
  iconSize: 64,
  icon: AnimatedIcon(
    icon: AnimatedIcons.play_pause,
    progress: _animationController,
    color: Colors.white,
  ),
  onPressed: () {
    widget.isPlaying
        ? _animationController.reverse()
        : _animationController.forward();
  },
);

You can look at the full source code here, but as you saw in the snippet above, you can easily create this morphing animation using AnimationController together with Flutter’s built-in animated icons. Simple, right?

And that’s all for now, folks! If you’re interested in discussing mobile development or need help building a mobile product, Pink Room is here to help.

Don't forget to share on your socials

Making Flutter Mobile Apps Shine with 3 Easy UI Effects — Part II

by
Bruno Correia
·
March 20, 2025
Engineering

Bridging Compose Multiplatform with SwiftUI

by
Lucas Prioste
·
June 12, 2025
Engineering

Making Flutter Mobile Apps Shine with 3 Easy UI Effects — Part I

by
Bruno Correia
·
February 27, 2025
Engineering

The Pink Room Way, Part 0: Turning Dreams Into Digital Realities

by
Mário Gago
·
October 25, 2023
Pink Room Way