From a7d2f8359f99aa5cc02e9b8faec918b9744d846d Mon Sep 17 00:00:00 2001 From: Mehmet Fidanboylu Date: Tue, 29 Aug 2017 09:39:54 -0700 Subject: [PATCH] Notify the completer after the close animation completes on the snackbar (#11688) * Notify the completer after the close animation completes on the snackbar * Review comments * Fix tests and analyzer warnings * Fix analyzer warnings --- packages/flutter/lib/src/material/scaffold.dart | 10 +++++++--- packages/flutter/test/material/snack_bar_test.dart | 14 +++++++++----- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/packages/flutter/lib/src/material/scaffold.dart b/packages/flutter/lib/src/material/scaffold.dart index 426b01a4fed..ec14c1c287f 100644 --- a/packages/flutter/lib/src/material/scaffold.dart +++ b/packages/flutter/lib/src/material/scaffold.dart @@ -605,14 +605,18 @@ class ScaffoldState extends State with TickerProviderStateMixin { } /// Removes the current [SnackBar] by running its normal exit animation. + /// + /// The closed completer is called after the animation is complete. void hideCurrentSnackBar({ SnackBarClosedReason reason: SnackBarClosedReason.hide }) { assert(reason != null); if (_snackBars.isEmpty || _snackBarController.status == AnimationStatus.dismissed) return; final Completer completer = _snackBars.first._completer; - if (!completer.isCompleted) - completer.complete(reason); - _snackBarController.reverse(); + _snackBarController.reverse().then((Null _) { + assert(mounted); + if (!completer.isCompleted) + completer.complete(reason); + }); _snackBarTimer?.cancel(); _snackBarTimer = null; } diff --git a/packages/flutter/test/material/snack_bar_test.dart b/packages/flutter/test/material/snack_bar_test.dart index 78ced10ca87..a050f06f7ae 100644 --- a/packages/flutter/test/material/snack_bar_test.dart +++ b/packages/flutter/test/material/snack_bar_test.dart @@ -374,7 +374,11 @@ void main() { expect(actionPressed, isFalse); await tester.tap(find.text('ACTION')); expect(actionPressed, isTrue); - await tester.pump(const Duration(seconds: 1)); + // Closed reason is only set when the animation is complete. + await tester.pump(const Duration(milliseconds:250)); + expect(closedReason, isNull); + // Wait for animation to complete. + await tester.pumpAndSettle(const Duration(seconds: 1)); expect(closedReason, equals(SnackBarClosedReason.action)); // Pop up the snack bar and then swipe downwards to dismiss it. @@ -382,21 +386,21 @@ void main() { await tester.pump(const Duration(milliseconds: 750)); await tester.pump(const Duration(milliseconds: 750)); await tester.drag(find.text('snack'), const Offset(0.0, 50.0)); - await tester.pump(); + await tester.pumpAndSettle(const Duration(seconds: 1)); expect(closedReason, equals(SnackBarClosedReason.swipe)); // Pop up the snack bar and then remove it. await tester.tap(find.text('X')); await tester.pump(const Duration(milliseconds: 750)); scaffoldKey.currentState.removeCurrentSnackBar(); - await tester.pump(const Duration(seconds: 1)); + await tester.pumpAndSettle(const Duration(seconds: 1)); expect(closedReason, equals(SnackBarClosedReason.remove)); // Pop up the snack bar and then hide it. await tester.tap(find.text('X')); await tester.pump(const Duration(milliseconds: 750)); scaffoldKey.currentState.hideCurrentSnackBar(); - await tester.pump(const Duration(seconds: 1)); + await tester.pumpAndSettle(const Duration(seconds: 1)); expect(closedReason, equals(SnackBarClosedReason.hide)); // Pop up the snack bar and then let it time out. @@ -405,7 +409,7 @@ void main() { await tester.pump(const Duration(milliseconds: 750)); await tester.pump(const Duration(milliseconds: 1500)); await tester.pump(); // begin animation - await tester.pump(const Duration(milliseconds: 750)); + await tester.pumpAndSettle(const Duration(seconds: 1)); expect(closedReason, equals(SnackBarClosedReason.timeout)); });