Unverified Commit b2310527 authored by Bruno Leroux's avatar Bruno Leroux Committed by GitHub

Expose barrierDismissible in PageRoute constructor (#133659)

## Description

This PR exposes `barrierDismissible` in `PageRoute`, `MaterialPageRoute` and `CupertinoPageRoute` constructors.
Setting this property to true will enable the escape key binding.

## Related Issue

Fixes https://github.com/flutter/flutter/issues/132138.

## Tests

Adds one test.
parent 15048a6b
...@@ -311,6 +311,9 @@ mixin CupertinoRouteTransitionMixin<T> on PageRoute<T> { ...@@ -311,6 +311,9 @@ mixin CupertinoRouteTransitionMixin<T> on PageRoute<T> {
/// the route is popped from the stack via [Navigator.pop] when an optional /// the route is popped from the stack via [Navigator.pop] when an optional
/// `result` can be provided. /// `result` can be provided.
/// ///
/// If `barrierDismissible` is true, then pressing the escape key on the keyboard
/// will cause the current route to be popped with null as the value.
///
/// See also: /// See also:
/// ///
/// * [CupertinoRouteTransitionMixin], for a mixin that provides iOS transition /// * [CupertinoRouteTransitionMixin], for a mixin that provides iOS transition
...@@ -334,6 +337,7 @@ class CupertinoPageRoute<T> extends PageRoute<T> with CupertinoRouteTransitionMi ...@@ -334,6 +337,7 @@ class CupertinoPageRoute<T> extends PageRoute<T> with CupertinoRouteTransitionMi
this.maintainState = true, this.maintainState = true,
super.fullscreenDialog, super.fullscreenDialog,
super.allowSnapshotting = true, super.allowSnapshotting = true,
super.barrierDismissible = false,
}) { }) {
assert(opaque); assert(opaque);
} }
......
...@@ -20,6 +20,9 @@ import 'theme.dart'; ...@@ -20,6 +20,9 @@ import 'theme.dart';
/// fullscreen modal dialog. On iOS, those routes animate from the bottom to the /// fullscreen modal dialog. On iOS, those routes animate from the bottom to the
/// top rather than horizontally. /// top rather than horizontally.
/// ///
/// If `barrierDismissible` is true, then pressing the escape key on the keyboard
/// will cause the current route to be popped with null as the value.
///
/// The type `T` specifies the return type of the route which can be supplied as /// The type `T` specifies the return type of the route which can be supplied as
/// the route is popped from the stack via [Navigator.pop] by providing the /// the route is popped from the stack via [Navigator.pop] by providing the
/// optional `result` argument. /// optional `result` argument.
...@@ -40,6 +43,7 @@ class MaterialPageRoute<T> extends PageRoute<T> with MaterialRouteTransitionMixi ...@@ -40,6 +43,7 @@ class MaterialPageRoute<T> extends PageRoute<T> with MaterialRouteTransitionMixi
this.maintainState = true, this.maintainState = true,
super.fullscreenDialog, super.fullscreenDialog,
super.allowSnapshotting = true, super.allowSnapshotting = true,
super.barrierDismissible = false,
}) { }) {
assert(opaque); assert(opaque);
} }
......
...@@ -11,6 +11,9 @@ import 'routes.dart'; ...@@ -11,6 +11,9 @@ import 'routes.dart';
/// The [PageRouteBuilder] subclass provides a way to create a [PageRoute] using /// The [PageRouteBuilder] subclass provides a way to create a [PageRoute] using
/// callbacks rather than by defining a new class via subclassing. /// callbacks rather than by defining a new class via subclassing.
/// ///
/// If `barrierDismissible` is true, then pressing the escape key on the keyboard
/// will cause the current route to be popped with null as the value.
///
/// See also: /// See also:
/// ///
/// * [Route], which documents the meaning of the `T` generic type argument. /// * [Route], which documents the meaning of the `T` generic type argument.
...@@ -20,7 +23,8 @@ abstract class PageRoute<T> extends ModalRoute<T> { ...@@ -20,7 +23,8 @@ abstract class PageRoute<T> extends ModalRoute<T> {
super.settings, super.settings,
this.fullscreenDialog = false, this.fullscreenDialog = false,
this.allowSnapshotting = true, this.allowSnapshotting = true,
}); bool barrierDismissible = false,
}) : _barrierDismissible = barrierDismissible;
/// {@template flutter.widgets.PageRoute.fullscreenDialog} /// {@template flutter.widgets.PageRoute.fullscreenDialog}
/// Whether this page route is a full-screen dialog. /// Whether this page route is a full-screen dialog.
...@@ -39,7 +43,8 @@ abstract class PageRoute<T> extends ModalRoute<T> { ...@@ -39,7 +43,8 @@ abstract class PageRoute<T> extends ModalRoute<T> {
bool get opaque => true; bool get opaque => true;
@override @override
bool get barrierDismissible => false; bool get barrierDismissible => _barrierDismissible;
final bool _barrierDismissible;
@override @override
bool canTransitionTo(TransitionRoute<dynamic> nextRoute) => nextRoute is PageRoute; bool canTransitionTo(TransitionRoute<dynamic> nextRoute) => nextRoute is PageRoute;
......
...@@ -11,6 +11,7 @@ import 'package:flutter/cupertino.dart' show CupertinoPageRoute; ...@@ -11,6 +11,7 @@ import 'package:flutter/cupertino.dart' show CupertinoPageRoute;
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
void main() { void main() {
...@@ -1229,6 +1230,45 @@ void main() { ...@@ -1229,6 +1230,45 @@ void main() {
expect(find.text('p1'), findsOneWidget); expect(find.text('p1'), findsOneWidget);
expect(find.text('count: 1'), findsOneWidget); expect(find.text('count: 1'), findsOneWidget);
}); });
testWidgets('MaterialPageRoute can be dismissed with escape keyboard shortcut', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/132138.
final GlobalKey scaffoldKey = GlobalKey();
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
key: scaffoldKey,
body: Center(
child: ElevatedButton(
onPressed: () {
Navigator.push<void>(scaffoldKey.currentContext!, MaterialPageRoute<void>(
builder: (BuildContext context) {
return const Scaffold(
body: Center(child: Text('route')),
);
},
barrierDismissible: true,
));
},
child: const Text('push'),
),
),
),
),
);
await tester.tap(find.text('push'));
await tester.pumpAndSettle();
expect(find.text('route'), findsOneWidget);
expect(find.text('push'), findsNothing);
// Try to dismiss the route with the escape key.
await tester.sendKeyEvent(LogicalKeyboardKey.escape);
await tester.pumpAndSettle();
expect(find.text('route'), findsNothing);
});
} }
class TransitionDetector extends DefaultTransitionDelegate<void> { class TransitionDetector extends DefaultTransitionDelegate<void> {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment