flutteranimationfloating-action-buttonscaffold

Cannot disable appearance animations on a "floatingActionButton" widget


The floatingActionButton property of Scaffold accepts any widget, so I use there a row of a few custom containers to take advantage of the floating effect. I've set the floatingActionButtonLocation property to "centerFloat". The problem is, that whenever I push a new page with such a widget, it uses a weird animation that I want to disable. I found this: Disable Scaffold FAB animation, so I extended FloatingActionButtonAnimator and tried what was shown in the aforementioned example, but unfortunately, it didn't help. I dealt with the offset easily. but the rotation and scale animation persist. Even tweaking the begin and end values of the Tween object doesn't help.

This is the setup in the Scaffold:

    floatingActionButton: ActionControls(),
    floatingActionButtonLocation:
        FloatingActionButtonLocation.centerFloat,
    floatingActionButtonAnimator: NoScalingAnimation(),

Those are the ActionControls, that are basically my floating buttons:

class ActionControls extends StatelessWidget {
  Widget _iconButton({
    @required BuildContext context,
    @required IconData icon,
    @required Function function,
    Color color,
  }) {
    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 10),
      decoration: BoxDecoration(
        borderRadius: BorderRadius.circular(5),
        color: color == null ? Theme.of(context).accentColor : color,
      ),
      child: IconButton(
        icon: Icon(
          icon,
          size: 30,
          color: Colors.white,
        ),
        onPressed: function,
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisSize: MainAxisSize.min,
      children: <Widget>[
        _iconButton(
          context: context,
          icon: Icons.keyboard_arrow_left,
          function: () {},
        ),
        const SizedBox(width: 10),
        _iconButton(
          context: context,
          icon: Icons.add,
          function: () {},
        ),
      ],
    );
  }
}

And this is my FloatingActionButtonAnimator:

class NoScalingAnimation extends FloatingActionButtonAnimator {
  @override
  Offset getOffset({Offset begin, Offset end, double progress}) {
    return end;
  }

  @override
  Animation<double> getRotationAnimation({Animation<double> parent}) {
    return Tween<double>(begin: 1.0, end: 1.0).animate(parent);
  }

  @override
  Animation<double> getScaleAnimation({Animation<double> parent}) {
    return Tween<double>(begin: 1.0, end: 1.0).animate(parent);
  }
}

Problematic animation example: https://i.sstatic.net/Rf0OS.jpg


Solution

  • FloatingActionButton has a parameter herotag, if you do not define it it will use a defaultHeroTag, when pushing to a new page it checks herotags with same name and applies the animation.

    FloatingActionButton(
      heroTag: "MyFirstPage", //give it a custom name to avoid same heroTag in each page
      ...
     )
    

    UPDATE

    class First extends StatelessWidget{
      
       @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(),
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Text('First'),
                RaisedButton(
                  onPressed: () {
                    Navigator.push(
                      context,
                      MaterialPageRoute(
                        builder: (context) => Second(),
                      ),
                    );
                  },
                  child: Text('Page'),
                ),
              ],
            ),
          ),
          floatingActionButton: ActionControls(),
          floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
          floatingActionButtonAnimator: NoScalingAnimation(),
        );
      }
    }
    
    class Second extends StatelessWidget{
      
      @override
      Widget build(BuildContext context){
        return Scaffold(
          appBar: AppBar(),
          body: Center(child: Text('My Second Page')),
          floatingActionButton: ActionControls(),
          floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
          floatingActionButtonAnimator: NoScalingAnimation(),
          /*
          floatingActionButton: FloatingActionButton(
            child: const Icon(Icons.add),
            onPressed: () => print('tapped')
          ),
          */
        );
      }
    }
    
    class ActionControls extends StatelessWidget {
      Widget _iconButton({
        @required BuildContext context,
        @required IconData icon,
        @required Function function,
        Color color,
      }) {
        return Container(
          padding: const EdgeInsets.symmetric(horizontal: 10),
          decoration: BoxDecoration(
            borderRadius: BorderRadius.circular(5),
            color: color == null ? Theme.of(context).accentColor : color,
          ),
          child: IconButton(
            icon: Icon(
              icon,
              size: 30,
              color: Colors.white,
            ),
            onPressed: function,
          ),
        );
      }
    
      @override
      Widget build(BuildContext context) {
        return Row(
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[
            _iconButton(
              context: context,
              icon: Icons.keyboard_arrow_left,
              function: () {},
            ),
            const SizedBox(width: 10),
            _iconButton(
              context: context,
              icon: Icons.add,
              function: () {},
            ),
          ],
        );
      }
    }
    
    class NoScalingAnimation extends FloatingActionButtonAnimator {
      @override
      Offset getOffset({Offset begin, Offset end, double progress}) {
        return end;
      }
    
      @override
      Animation<double> getRotationAnimation({Animation<double> parent}) {
        return Tween<double>(begin: 1.0, end: 1.0).animate(parent);
      }
    
      @override
      Animation<double> getScaleAnimation({Animation<double> parent}) {
        return Tween<double>(begin: 1.0, end: 1.0).animate(parent);
      }
    }
    

    I made a minimal reproducible code sample and I didn't find any animation between the first and second page, even changing in the second page the position to FloatingActionButtonLocation.endFloat or actually inserting a FloatingActionButton(). The only animation I see is from the MaterialPageRoute fade from below animation