mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
Merge pull request #310 from HansMuller/snack_bar
showSnackBar() returns a Future, clears its placeholder The returned Future completes after the snack bar has been dismissed. Revised BottomSheet to ensure that its Future only runs after the bottom sheet has been dismissed.
This commit is contained in:
commit
3f58d9b7c9
@ -77,10 +77,14 @@ class _BottomSheetRoute extends OverlayRoute {
|
||||
}
|
||||
|
||||
void didPop(dynamic result) {
|
||||
completer.complete(result);
|
||||
performance.reverse().then((_) {
|
||||
void finish() {
|
||||
super.didPop(result); // clear the overlay entries
|
||||
});
|
||||
completer.complete(result);
|
||||
}
|
||||
if (performance.isDismissed)
|
||||
finish();
|
||||
else
|
||||
performance.reverse().then((_) { finish(); });
|
||||
}
|
||||
|
||||
String get debugLabel => '$runtimeType';
|
||||
|
@ -2,6 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/animation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
@ -92,12 +94,15 @@ class _SnackBar extends StatelessComponent {
|
||||
}
|
||||
|
||||
class _SnackBarRoute extends TransitionRoute {
|
||||
_SnackBarRoute({ Completer completer }) : super(completer: completer);
|
||||
|
||||
bool get opaque => false;
|
||||
Duration get transitionDuration => const Duration(milliseconds: 200);
|
||||
}
|
||||
|
||||
void showSnackBar({ BuildContext context, GlobalKey<PlaceholderState> placeholderKey, Widget content, List<SnackBarAction> actions }) {
|
||||
_SnackBarRoute route = new _SnackBarRoute();
|
||||
Future showSnackBar({ BuildContext context, GlobalKey<PlaceholderState> placeholderKey, Widget content, List<SnackBarAction> actions }) {
|
||||
final Completer completer = new Completer();
|
||||
_SnackBarRoute route = new _SnackBarRoute(completer: completer);
|
||||
_SnackBar snackBar = new _SnackBar(
|
||||
route: route,
|
||||
content: content,
|
||||
@ -105,4 +110,7 @@ void showSnackBar({ BuildContext context, GlobalKey<PlaceholderState> placeholde
|
||||
);
|
||||
placeholderKey.currentState.child = snackBar;
|
||||
Navigator.of(context).pushEphemeral(route);
|
||||
return completer.future.then((_) {
|
||||
placeholderKey.currentState.child = null;
|
||||
});
|
||||
}
|
||||
|
@ -2,6 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/animation.dart';
|
||||
|
||||
import 'basic.dart';
|
||||
@ -46,6 +48,10 @@ class OverlayRoute extends Route {
|
||||
|
||||
// TODO(abarth): Should we add a type for the result?
|
||||
abstract class TransitionRoute extends OverlayRoute {
|
||||
TransitionRoute({ this.completer });
|
||||
|
||||
final Completer completer;
|
||||
|
||||
Duration get transitionDuration;
|
||||
bool get opaque;
|
||||
|
||||
@ -86,7 +92,10 @@ abstract class TransitionRoute extends OverlayRoute {
|
||||
|
||||
void didPop(dynamic result) {
|
||||
_result = result;
|
||||
_performance.reverse();
|
||||
if (completer != null)
|
||||
_performance.reverse().then((_) { completer.complete(_result); });
|
||||
else
|
||||
_performance.reverse();
|
||||
}
|
||||
|
||||
String get debugLabel => '$runtimeType';
|
||||
|
@ -8,6 +8,8 @@ void main() {
|
||||
test('Verify that a tap dismisses a modal BottomSheet', () {
|
||||
testWidgets((WidgetTester tester) {
|
||||
BuildContext context;
|
||||
bool showBottomSheetThenCalled = false;
|
||||
|
||||
tester.pumpWidget(new MaterialApp(
|
||||
routes: <String, RouteBuilder>{
|
||||
'/': (RouteArguments args) {
|
||||
@ -20,7 +22,10 @@ void main() {
|
||||
tester.pump();
|
||||
expect(tester.findText('BottomSheet'), isNull);
|
||||
|
||||
showModalBottomSheet(context: context, child: new Text('BottomSheet'));
|
||||
showModalBottomSheet(context: context, child: new Text('BottomSheet')).then((_) {
|
||||
showBottomSheetThenCalled = true;
|
||||
});
|
||||
|
||||
tester.pump(); // bottom sheet show animation starts
|
||||
tester.pump(new Duration(seconds: 1)); // animation done
|
||||
expect(tester.findText('BottomSheet'), isNotNull);
|
||||
@ -29,7 +34,8 @@ void main() {
|
||||
tester.tap(tester.findText('BottomSheet'));
|
||||
tester.pump(); // bottom sheet dismiss animation starts
|
||||
tester.pump(new Duration(seconds: 1)); // animation done
|
||||
tester.pump(new Duration(seconds: 2)); // rebuild frame
|
||||
tester.pump(new Duration(seconds: 1)); // rebuild frame
|
||||
expect(showBottomSheetThenCalled, isTrue);
|
||||
expect(tester.findText('BottomSheet'), isNull);
|
||||
|
||||
showModalBottomSheet(context: context, child: new Text('BottomSheet'));
|
||||
@ -41,7 +47,7 @@ void main() {
|
||||
tester.tapAt(new Point(20.0, 20.0));
|
||||
tester.pump(); // bottom sheet dismiss animation starts
|
||||
tester.pump(new Duration(seconds: 1)); // animation done
|
||||
tester.pump(new Duration(seconds: 2)); // rebuild frame
|
||||
tester.pump(new Duration(seconds: 1)); // rebuild frame
|
||||
expect(tester.findText('BottomSheet'), isNull);
|
||||
});
|
||||
});
|
||||
@ -50,6 +56,8 @@ void main() {
|
||||
testWidgets((WidgetTester tester) {
|
||||
GlobalKey<PlaceholderState> _bottomSheetPlaceholderKey = new GlobalKey<PlaceholderState>();
|
||||
BuildContext context;
|
||||
bool showBottomSheetThenCalled = false;
|
||||
|
||||
tester.pumpWidget(new MaterialApp(
|
||||
routes: <String, RouteBuilder>{
|
||||
'/': (RouteArguments args) {
|
||||
@ -69,7 +77,9 @@ void main() {
|
||||
context: context,
|
||||
child: new Container(child: new Text('BottomSheet'), margin: new EdgeDims.all(40.0)),
|
||||
placeholderKey: _bottomSheetPlaceholderKey
|
||||
);
|
||||
).then((_) {
|
||||
showBottomSheetThenCalled = true;
|
||||
});
|
||||
|
||||
expect(_bottomSheetPlaceholderKey.currentState.child, isNotNull);
|
||||
tester.pump(); // bottom sheet show animation starts
|
||||
@ -79,7 +89,8 @@ void main() {
|
||||
tester.fling(tester.findText('BottomSheet'), const Offset(0.0, 20.0), 1000.0);
|
||||
tester.pump(); // bottom sheet dismiss animation starts
|
||||
tester.pump(new Duration(seconds: 1)); // animation done
|
||||
tester.pump(new Duration(seconds: 2)); // rebuild frame without the bottom sheet
|
||||
tester.pump(new Duration(seconds: 1)); // rebuild frame without the bottom sheet
|
||||
expect(showBottomSheetThenCalled, isTrue);
|
||||
expect(tester.findText('BottomSheet'), isNull);
|
||||
expect(_bottomSheetPlaceholderKey.currentState.child, isNull);
|
||||
});
|
||||
|
@ -9,17 +9,22 @@ void main() {
|
||||
String helloSnackBar = 'Hello SnackBar';
|
||||
GlobalKey<PlaceholderState> placeholderKey = new GlobalKey<PlaceholderState>();
|
||||
Key tapTarget = new Key('tap-target');
|
||||
BuildContext context;
|
||||
bool showSnackBarThenCalled = false;
|
||||
|
||||
tester.pumpWidget(new MaterialApp(
|
||||
routes: <String, RouteBuilder>{
|
||||
'/': (RouteArguments args) {
|
||||
context = args.context;
|
||||
return new GestureDetector(
|
||||
onTap: () {
|
||||
showSnackBar(
|
||||
context: args.context,
|
||||
placeholderKey: placeholderKey,
|
||||
content: new Text(helloSnackBar)
|
||||
);
|
||||
).then((_) {
|
||||
showSnackBarThenCalled = true;
|
||||
});
|
||||
},
|
||||
child: new Container(
|
||||
decoration: const BoxDecoration(
|
||||
@ -36,10 +41,16 @@ void main() {
|
||||
));
|
||||
|
||||
tester.tap(tester.findElementByKey(tapTarget));
|
||||
|
||||
expect(tester.findText(helloSnackBar), isNull);
|
||||
tester.pump();
|
||||
expect(tester.findText(helloSnackBar), isNotNull);
|
||||
|
||||
Navigator.of(context).pop();
|
||||
expect(tester.findText(helloSnackBar), isNotNull);
|
||||
tester.pump(new Duration(seconds: 1));
|
||||
expect(showSnackBarThenCalled, isTrue);
|
||||
expect(tester.findText(helloSnackBar), isNull);
|
||||
expect(placeholderKey.currentState.child, isNull);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user