hero_here 1.0.1 copy "hero_here: ^1.0.1" to clipboard
hero_here: ^1.0.1 copied to clipboard

Hero transitions on the same screen without the need for navigation.

A Flutter library that enables hero transitions on the same screen without the need for navigation.

The hero_here basic example   The hero_here chat message example   The hero_here show details example

Purpose #

hero_here is designed to help developers create seamless and visually appealing transitions within a single screen using the hero animation pattern. It is inspired by Flutter's AnimatedSwitcher and Hero mechanics and provides a convenient way to achieve these transitions without requiring navigation.

Features #

  • Allows hero transitions within the same screen.
  • Similar widgets to AnimatedSwitcher and Hero: HeroHereSwitcher and HeroHere.
  • Customizable flight animations

Getting Started #

Add the following line to your pubspec.yaml file:

dependencies:
  hero_here: ^1.0.0

Then, run:

flutter pub get

Usage #

Here’s a basic example of how to use hero_here:

import 'package:flutter/material.dart';
import 'package:hero_here/hero_here.dart';

const kHeroTag = 'hero';

void main() => runApp(
      MaterialApp(
        title: 'HeroHere Example',
        debugShowCheckedModeBanner: false,
        theme: ThemeData(useMaterial3: true, brightness: Brightness.light),
        darkTheme: ThemeData(useMaterial3: true, brightness: Brightness.dark),
        home: const HeroHereExample(),
      ),
    );

enum HeroType { red, green }

class HeroHereExample extends StatefulWidget {
  const HeroHereExample({super.key});

  @override
  State<HeroHereExample> createState() => _HeroHereExampleState();
}

class _HeroHereExampleState extends State<HeroHereExample> {
  HeroType _curHeroType = HeroType.red;

  HeroType get curHeroType => _curHeroType;

  set curHeroType(HeroType value) {
    if (_curHeroType == value) return;
    setState(() => _curHeroType = value);
  }

  @override
  Widget build(BuildContext context) => Scaffold(
        body: HeroHereSwitcher(
          child: Center(
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                SizedBox(
                  width: 100,
                  height: 100,
                  child: curHeroType == HeroType.red
                      ? HeroHere(
                          key: const ValueKey(HeroType.red),
                          tag: kHeroTag,
                          flightShuttleBuilder: _flightShuttleBuilder,
                          child: Container(
                            decoration: BoxDecoration(
                              color: Colors.red,
                              borderRadius: BorderRadius.circular(75),
                            ),
                          ),
                        )
                      : null,
                ),
                SizedBox(
                  width: 150,
                  height: 150,
                  child: curHeroType == HeroType.green
                      ? HeroHere(
                          key: const ValueKey(HeroType.green),
                          tag: kHeroTag,
                          flightShuttleBuilder: _flightShuttleBuilder,
                          child: Container(
                            decoration: BoxDecoration(
                              color: Colors.green,
                              borderRadius: BorderRadius.circular(75),
                            ),
                          ),
                        )
                      : null,
                ),
              ],
            ),
          ),
        ),
        bottomNavigationBar: BottomAppBar(
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: [
              Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  IconButton(
                    onPressed: () => curHeroType = HeroType.red,
                    icon: Icon(curHeroType == HeroType.red
                        ? Icons.circle
                        : Icons.radio_button_off),
                    color: curHeroType == HeroType.red
                        ? Colors.red
                        : Theme.of(context).colorScheme.secondary,
                  ),
                ],
              ),
              Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  IconButton(
                    onPressed: () => curHeroType = HeroType.green,
                    icon: Icon(curHeroType == HeroType.green
                        ? Icons.circle
                        : Icons.radio_button_off),
                    color: curHeroType == HeroType.green
                        ? Colors.green
                        : Theme.of(context).colorScheme.secondary,
                  ),
                ],
              ),
            ],
          ),
        ),
      );

  Widget _flightShuttleBuilder(
    BuildContext flightContext,
    Animation<double> animation,
    HeroHere fromHero,
    HeroHere toHero,
  ) =>
      Stack(
        fit: StackFit.expand,
        children: [
          toHero.child,
          FadeTransition(
            opacity: ReverseAnimation(animation),
            child: fromHero.child,
          ),
        ],
      );
}

More advanced examples can be found in the example folder or by following this link.

Support and Contact #

For any questions or issues related to hero_here, please contact me via email at mail@igorkurilenko.dev.

Contributing #

Contributions are welcome! Feel free to submit pull requests on GitHub to help improve hero_here.

Author and License #

hero_here was created by Igor Kurilenko and is licensed under Apache 2.0.

14
likes
140
points
126
downloads

Publisher

verified publisherigorkurilenko.dev

Weekly Downloads

Hero transitions on the same screen without the need for navigation.

Repository (GitHub)

Documentation

API reference

License

Apache-2.0 (license)

Dependencies

flutter

More

Packages that depend on hero_here