hero_here 2.3.4
hero_here: ^2.3.4 copied to clipboard
Hero animation within the same page: tag a widget's old and new places alike, change state, and it flies from one to the other. No Navigator or routes.
Flutter hero animation example
This Flutter hero animation example is the flippers example from Flutter's hero animations guide, on the same page: tap the photo, and it flies from the middle of the page into its corner, without navigation, as a hero widget flies between routes.1 Tap it again, and it flies back.
See the flippers code › Install hero_here ›
Get the highlights. #
- No route. The photo flies within the page, as the page changes its state. Nothing is pushed or popped.
- Two places. One tag. The photo is a
HeroHerein the middle of the page and another in its corner, both tagged'flippers'. - Back again. Tap the photo in the corner, and it flies back to the middle.
- As in the guide. The same photo and sizes as in Flutter's hero animations guide, without its second route.
Take a closer look. #
Three steps, all in one build method:
- The switcher. A
HeroHereSwitcherwraps the page's body. - The heroes. The photo is a
HeroHere: 300 wide in the middle of the page, or 100 wide in its corner. Both have the tag'flippers', and each has a key of its own. - The change. A tap moves the photo to the other place, and the switcher flies it there.
import 'package:flutter/material.dart';
import 'package:hero_here/hero_here.dart';
void main() => runApp(
const MaterialApp(
title: 'HeroHere Example',
debugShowCheckedModeBanner: false,
home: FlippersExample(),
),
);
/// The flippers photo from Flutter's hero animations guide, flying between
/// the middle of the page and its corner, within the page:
///
/// 1. A [HeroHereSwitcher] wraps the page's body.
/// 2. The photo is a [HeroHere], in the middle or in the corner: with the
/// same tag in both places, and a key of its own in each.
/// 3. A tap moves the photo to the other place, and the switcher flies it
/// there.
class FlippersExample extends StatefulWidget {
const FlippersExample({super.key});
@override
State<FlippersExample> createState() => _FlippersExampleState();
}
class _FlippersExampleState extends State<FlippersExample> {
var _inCorner = false;
@override
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(title: const Text('Basic Hero Animation')),
body: GestureDetector(
// 3. A tap moves the photo to the other place.
onTap: () => setState(() => _inCorner = !_inCorner),
// 1. The switcher.
child: HeroHereSwitcher(
// 2. The photo, in the corner or in the middle.
child: _inCorner
? Align(
alignment: Alignment.topLeft,
child: SizedBox(
width: 100,
child: HeroHere(
key: const ValueKey('corner'), // Its own key in each place.
tag: 'flippers', // The same tag in both places.
child: Image.asset('images/flippers.png'),
),
),
)
: Center(
child: SizedBox(
width: 300,
child: HeroHere(
key: const ValueKey('center'),
tag: 'flippers',
child: Image.asset('images/flippers.png'),
),
),
),
),
),
);
}
More ways to use hero_here. #
Seven more Flutter hero animation examples, each a pattern apps often need, built with a HeroHereSwitcher and its heroes, and each recorded as it runs.2 They're code to learn from and copy, not widgets to import. Run one from the repository's example folder, such as with flutter run -t lib/add_to_cart_hero/main.dart. In each, main.dart places the heroes, and a file beside it draws the rest.
Flip card animation #
Tap a card in a grid, and it flies to the middle of the screen on a bouncy spring, turning over in a card flip animation to show its back, like a flash card. HeroHereShuttles.flip turns it over in flight. Tap it again, or beside it, and it flies back to the grid. See the flip card code ›
Pinterest-style image details #
A shared element transition from a Pinterest-style grid: tap an image, and it opens into its details, with its title and description flying along, as in a container transform or an open container animation, but with no route. Pull the image down, and this card expand animation runs back into the grid, the image as fast as the pull let go. See the image details code ›
Add to cart animation #
Tap add to cart, and the product's image lifts off its card and flies into the cart, landing on a soft spring,3 as in an e-commerce app. Remove it, and it flies back, as the items after it in the cart slide along. Its flightShuttleBuilder lifts it off the page with a shadow that grows as it takes off and fades as it lands. Each product's image is a HeroHere on its card or in the cart, with the product's name as its tag in both places. Its position in the cart is part of its key there, so when one item leaves, the ones after it fly along. See the add to cart code ›
Splash screen animation #
Once the app has loaded, the logo and the app name fly from the middle of the splash screen into the app bar, landing on a soft spring: an animated splash screen with a logo animation, on the same page as the content, with no route of its own. The name scales with HeroHereShuttles.scale rather than laying out anew, so its text doesn't reflow in flight. See the splash screen code ›
Animated bottom navigation bar #
An animated bottom navigation bar: tap a tab, and its sliding indicator flies there under the icons, in a bottom navigation bar animation with no offsets to compute. The indicator is a HeroHere on the selected tab, and HeroHereSwitcher.skyUnderLayoutBuilder flies it under the icons. Tap another tab before it lands, and it starts over toward that one from where it is, with HeroHereFlightRedirect.restart. See the navigation bar code ›
Sliding segmented control #
A sliding segmented control, or animated toggle switch, for any number of options: the thumb slides under the labels to the tapped segment, as in the Cupertino sliding segmented control, but built from your own widgets. The thumb is a HeroHere in the selected segment, which HeroHereSwitcher.skyUnderLayoutBuilder flies under the labels. A tap mid-flight starts it over from where it is, with HeroHereFlightRedirect.restart. See the segmented control code ›
Chat message animation #
Send a message, and it flies from the text field up into the conversation, landing on a soft spring, as in messaging apps: a chat message animation for any chat UI. The spring is set on the message's hero in the conversation only, since a flight takes its options from the hero it flies to. See the chat message code ›
Questions? Answers. #
How do I make an add to cart animation in Flutter?
Wrap the page in a HeroHereSwitcher, and show each product's picture as a HeroHere where it is: on its card, or in the cart. Give it the same tag in both places, and a key of its own in each. Then add the product to the cart in setState, and the picture flies from its card to the cart, as in the add to cart example.
Why doesn't my widget fly?
When a hero animation is not working, check two things. Its old and its new place both need a HeroHere with the same tag, in the same HeroHereSwitcher. And each needs a key of its own: a hero with the same key is the same hero, which shows where it is now rather than flying there.
What if the user taps again mid-flight?
The flight changes course, as its heroes' flightRedirect says. With chain, the default, it lands first, then flies on. With divert, it turns toward the new place at the speed it had. With restart, it starts over toward it from where it is, as the navigation bar's indicator does.
Can a hero fly under other widgets?
Yes. Set the switcher's layoutBuilder to HeroHereSwitcher.skyUnderLayoutBuilder, and its heroes fly under its child, as the segmented control's thumb flies under the labels.
1. The flippers photo is from Flutter's hero animations guide, in the flutter/website repository, used under its license.
2. Recorded from the examples frame by frame, at 60 fps, in an iPhone 15 frame.
3. The soft spring is SpringDescription.withDurationAndBounce, at 500 ms with a bounce of 0.25, in lib/style/motion.dart.