diff --git a/packages/flutter/lib/src/material/scaffold.dart b/packages/flutter/lib/src/material/scaffold.dart index 7d40251848..fbcd472801 100644 --- a/packages/flutter/lib/src/material/scaffold.dart +++ b/packages/flutter/lib/src/material/scaffold.dart @@ -1358,11 +1358,9 @@ class _FloatingActionButtonTransitionState extends State<_FloatingActionButtonTr void _handlePreviousAnimationStatusChanged(AnimationStatus status) { setState(() { - if (status == AnimationStatus.dismissed) { + if (widget.child != null && status == AnimationStatus.dismissed) { assert(widget.currentController.status == AnimationStatus.dismissed); - if (widget.child != null) { - widget.currentController.forward(); - } + widget.currentController.forward(); } }); } diff --git a/packages/flutter/test/material/scaffold_test.dart b/packages/flutter/test/material/scaffold_test.dart index b204a7073a..55b38c18c8 100644 --- a/packages/flutter/test/material/scaffold_test.dart +++ b/packages/flutter/test/material/scaffold_test.dart @@ -2801,6 +2801,65 @@ void main() { // The scrim should be gone. expect(findModalBarrier(), findsNothing); }); + + testWidgets("Closing bottom sheet & removing FAB at the same time doesn't throw assertion", (WidgetTester tester) async { + final Key bottomSheetKey = UniqueKey(); + PersistentBottomSheetController? controller; + bool show = true; + + await tester.pumpWidget(StatefulBuilder( + builder: (_, StateSetter setState) => MaterialApp( + home: Scaffold( + body: Center( + child: Builder( + builder: (BuildContext context) => ElevatedButton( + onPressed: () { + if (controller == null) { + controller = showBottomSheet( + context: context, + builder: (_) => Container( + key: bottomSheetKey, + height: 200, + ), + ); + } else { + controller!.close(); + controller = null; + } + }, + child: const Text('BottomSheet'), + )), + ), + floatingActionButton: show + ? FloatingActionButton(onPressed: () => setState(() => show = false)) + : null, + ), + ), + )); + + // Show bottom sheet. + await tester.tap(find.byType(ElevatedButton)); + await tester.pumpAndSettle(const Duration(seconds: 1)); + + // Bottom sheet and FAB are visible. + expect(find.byType(FloatingActionButton), findsOneWidget); + expect(find.byKey(bottomSheetKey), findsOneWidget); + + // Close bottom sheet while removing FAB. + await tester.tap(find.byType(FloatingActionButton)); + await tester.pump(); // start animation + await tester.tap(find.byType(ElevatedButton)); + // Let the animation finish. + await tester.pumpAndSettle(const Duration(seconds: 1)); + + // Bottom sheet and FAB are gone. + expect(find.byType(FloatingActionButton), findsNothing); + expect(find.byKey(bottomSheetKey), findsNothing); + + // No exception is thrown. + expect(tester.takeException(), isNull); + }); + } class _GeometryListener extends StatefulWidget {