Skip to content

Staggered Menu Animation cookbook example: drawer close doesn't reverse the staggered item animation #13503

@petprog

Description

@petprog

Page URL

https://docs.flutter.dev/cookbook/effects/staggered-menu-animation

Page source

https://github.com/flutter/website/blob/main/sites/docs/src/content/cookbook/effects/staggered-menu-animation.md

Describe the problem

On the Staggered Menu Animation cookbook example, the closing animation doesn't mirror the opening one. The drawer slide (_drawerSlideController, 150ms) closes the panel, but the internal staggered item animation (_staggeredController inside _MenuState) only ever runs .forward() once in initState() and is never reversed.

_isDrawerClosed() checks only _drawerSlideController.value == 0.0. As soon as the 150ms slide finishes, this becomes true and _buildDrawer immediately swaps Menu() for SizedBox(), disposing the Menu widget's state entirely.

Result: opening shows a polished staggered entrance (panel slides in, then items animate in one by one with stagger + elastic button). Closing just slides the whole panel away as a solid block in 150ms — none of the menu items animate out, since their controller never reverses and the widget is torn down before anything could play.

Expected fix

Lift _staggeredController (and its Intervals) out of _MenuState and into _ExampleStaggeredAnimationsState, passing them into Menu as constructor parameters (Menu becomes a StatelessWidget). This keeps the controller alive across the drawer's full open/close lifecycle instead of being recreated/disposed with the widget.
In _toggleDrawer, sequence the close so items animate out first, then the panel slides away:

void _toggleDrawer() {
  if (_isDrawerOpen() || _isDrawerOpening()) {
    _staggeredController.reverse().whenCompleteOrCancel(() {
      _drawerSlideController.reverse();
    });
  } else {
    _drawerSlideController.forward();
    _staggeredController.forward(from: 0.0);
  }
}

Update _isDrawerClosed() to require both controllers at 0.0:

bool _isDrawerClosed() =>
    _drawerSlideController.value == 0.0 && _staggeredController.value == 0.0;

This keeps Menu mounted long enough for the staggered exit animation to finish before the panel itself is removed.

Additional context

Affects the example source linked above (staggered menu animation cookbook page)
Purely an animation-sequencing issue in the sample code, not platform/browser specific
Happy to open a PR with the corrected main.dart — I have a working version that fixes the close animation while keeping the existing open animation intact

I would like to fix this problem.

  • I will try and fix this problem on docs.flutter.dev.

Metadata

Metadata

Assignees

No one assigned

    Labels

    from.page-issueReported in a reader-filed concernp2-mediumNecessary but not urgent concern. Resolve when possible.

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions