Search code examples
flutterflutter-animationappbarflutter-appbar

Flutter AppBar Animation bugging in reverse


So, I'm building an app using Flutter, in the home page, I want to have a bigger AppBar, while in others, AppBar goes back to regular size, I managed to achieve the former in a good and smooth animation, but I couldn't get the latter to work.

Here's a code snippet from what I'm doing:

CustomAppBar class: import 'package:flutter/material.dart';

class CustomAppBar extends StatefulWidget implements PreferredSizeWidget{
  double height;
  String title;
  Color color;
  Color textColor;

  CustomAppBar(this.height, this.title, this.color, this.textColor, {super.key});

  @override
  State<CustomAppBar> createState() => _CustomAppBarState();

  @override
  // TODO: implement preferredSize
  Size get preferredSize => Size.fromHeight(height);
}

class _CustomAppBarState extends State<CustomAppBar> {
  @override
  Widget build(BuildContext context) {
    return PreferredSize(
      preferredSize: Size.fromHeight(widget.height),
      child: AnimatedContainer(
        duration: const Duration(milliseconds: 500),
        curve: Curves.decelerate,
        height: widget.height,
        child: Container(
          color: Colors.green,
        ),

      ),
    );
  }
}

Then in the Scaffold, I assign the AppBar like this:

appBar: CustomAppBar(height, getTitle(currentIndex), Colors.purple, Colors.white),

But I end up with an animation like this:

enter image description here

Notice how when clicking the second navigation item, it skips from height 260 to about 120, then animates from 120 to 90 (numbers are approximate)

Update: I tried adding the CustomAppBar to 'body' instead of 'appbar' and it weirdly worked, but I'd love to know what was causing the issue please.


Solution

  • I found out that the preferredSize getter override is causing the issue. I believe this happens because when the reverse animation is happening, it starts from the height that is taken from the preferredSize height, which makes it looks like jumping to that position before the animation actually takes you to the target height. The value of preferredSize is not animated, which is why you found out that it approximately starts from 120, because its change is not bounded to any duration.

    The good thing is, you can just set the preferredSize to the maximum height of the app bar, since the app bar is constrainted anyway. In the documentation of PreferredSizeWidget, it says:

    An interface for widgets that can return the size this widget would prefer if it were otherwise unconstrained.

    Your app bar is constrained to its own size, mainly in the height of the AnimatedContainer, so no need to worry about. You can just set it to a fixed value:

    @override
    Size get preferredSize => Size.fromHeight(260);
    

    And it will fix the animation issue.

    enter image description here