Flutter Animated Cross Fade overflow on transition

Issue

I have a button component that I want to show a loading spinner when it is told the component is loading. I animate between the loading and non loading states using AnimatedCrossFade.

My problem is: I get an overflow error when returning back to the original "non-loading" state. I know this is to do with the Row and having different sized widgets, but I have tried many combinations of flex widgets etc. and none work. I have also tried using Offstage on the change of this.isLoading. However that didn’t work either (and basically defeated the point of the animator).

Solutions that do solve the overflow issue, cause the button to become its maximum possible width which I don’t want all the time. The button needs to be able to take up the smallest amount of space it requires.

 @override
  Widget build(BuildContext context) {
    return ElevatedButton(
        onPressed: isLoading ? () => null : () => onPressed(),
        style: ButtonStyle(
            backgroundColor: MaterialStateProperty.all(primaryColour)),
        child: AnimatedCrossFade(
          duration: Duration(milliseconds: 400),
          crossFadeState:
              isLoading ? CrossFadeState.showSecond : CrossFadeState.showFirst,
          firstChild: Padding(
            padding:
                const EdgeInsets.symmetric(vertical: 8.0, horizontal: 10.0),
            child: this.child,
          ),
          secondChild: Row(
            mainAxisSize: MainAxisSize.min,
            children: [
              this.childWhenLoading,
              Padding(
                padding: const EdgeInsets.symmetric(horizontal: 8.0),
                child: SizedBox(
                  height: 20,
                  width: 20,
                  child: CircularProgressIndicator(
                    valueColor: AlwaysStoppedAnimation(Colours.white),
                    backgroundColor: primaryColour,
                    strokeWidth: 3,
                  ),
                ),
              )
            ],
          ),
        ));
  }

Solution

The Flutter team has addressed this here: https://youtu.be/PGK2UUAyE54?t=85.

I was facing this same issue and this worked for me:

AnimatedCrossFade(
  // ... Other arguments

  layoutBuilder: (topChild, topKey, bottomChild, bottomKey) {
    return Stack(
      alignment: Alignment.center,
      children: [
        Positioned(
          key: bottomChildKey,
          top: 0,
          child: bottomChild,
        ),
        Positioned(
          key: topChildKey,
          child: topChild,
        ),
      ],
    ),
  }
),

Answered By – cervonwong

Answer Checked By – Senaida (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *