Search code examples
flutterdartanimationflutter-animationhero

Flutter Hero animate 90 degree rotation


I am using Hero in my app for smooth transitions but I faced an issue: I would like the Hero-Widget rotate 90 degress on transition. I found out I can use flightShuttleBuilder for this and tried it like this:

flightShuttleBuilder: (
  BuildContext flightContext,
  Animation<double> animation,
  HeroFlightDirection flightDirection,
  BuildContext fromHeroContext,
  BuildContext toHeroContext,
) {
  final Widget toHero = toHeroContext.widget;
  return RotationTransition(
    turns: animation,
    child: toHero,
  );
},

As you can see I used the RotationTransition and it kind of works but not exactly how I want it. It rotates the widget during the flight by 360 instead of 90.

The widget should stay rotated on the 2nd screen. I tried that with RotatedBox. This is the full widget on the 2nd screen:

  child: Hero(
    tag: 'america',
    flightShuttleBuilder: (
      BuildContext flightContext,
      Animation<double> animation,
      HeroFlightDirection flightDirection,
      BuildContext fromHeroContext,
      BuildContext toHeroContext,
    ) {
      final Widget toHero = toHeroContext.widget;
      return RotationTransition(
        turns: animation.drive(Tween(begin: 0, end: 0.25)),
        child: toHero,
      );
    },
    child: RotatedBox(
      quarterTurns: 1,
      child: SizedBox(
        height: 100,
        width: 100,
        child: SvgPicture.asset(
          'assets/icons/america.svg',
        ),
      ),
    ),
  ),

Is there a way to get this done and how would I do that? Couldn't find anything on this. Let me know if you need any more info!


Solution

  • With the help of @Michael Horn I got it working. As he suggested I changed the turns value. That fixed the rotation. However I wanted the widget to stay rotated on the 2nd screen. I did that with RotatedBox. But when simply giving it the value 1, Hero will take that Rotated Widget for flightShuttleBuilder and the sets it back when building is finished. I fixed this by changing the quarterTurns after all the widgets are build:

      int rotation = 0;
      @override
      void initState() {
        super.initState();
        WidgetsBinding.instance!.addPostFrameCallback((timeStamp) {
          setState(() {
            rotation = 1;
          });
        });
      }
    

    and my widget:

      child: Hero(
        tag: 'america',
        flightShuttleBuilder: (
          BuildContext flightContext,
          Animation<double> animation,
          HeroFlightDirection flightDirection,
          BuildContext fromHeroContext,
          BuildContext toHeroContext,
        ) {
          final Widget toHero = toHeroContext.widget;
          return RotationTransition(
            turns: animation.drive(Tween(begin: 0, end: 0.25)), // <- for the during-flight 90 degree rotation
            child: toHero,
          );
        },
        child: RotatedBox(
          quarterTurns: rotation, // <- important to not change that dynamically
          child: SizedBox(
            height: 100,
            width: 100,
            child: SvgPicture.asset(
              'assets/icons/america.svg',
            ),
          ),
        ),
      ),