Commit 58a28a29 authored by Ian Hickson's avatar Ian Hickson Committed by GitHub

Improve some docs around WillPopScope. (#11429)

...and break the navigator<->routes circular dependency.

This is a step towards fixing https://github.com/flutter/flutter/issues/9577 but doesn't yet do so.
parent 764515ec
...@@ -29,6 +29,9 @@ typedef Future<LocaleQueryData> LocaleChangedCallback(Locale locale); ...@@ -29,6 +29,9 @@ typedef Future<LocaleQueryData> LocaleChangedCallback(Locale locale);
/// A convenience class that wraps a number of widgets that are commonly /// A convenience class that wraps a number of widgets that are commonly
/// required for an application. /// required for an application.
/// ///
/// One of the primary roles that [WidgetsApp] provides is binding the system
/// back button to popping the [Navigator] or quitting the application.
///
/// See also: [CheckedModeBanner], [DefaultTextStyle], [MediaQuery], /// See also: [CheckedModeBanner], [DefaultTextStyle], [MediaQuery],
/// [LocaleQuery], [Title], [Navigator], [Overlay], [SemanticsDebugger] (the /// [LocaleQuery], [Title], [Navigator], [Overlay], [SemanticsDebugger] (the
/// widgets wrapped by this one). /// widgets wrapped by this one).
......
...@@ -315,7 +315,7 @@ abstract class WidgetsBinding extends BindingBase with GestureBinding, RendererB ...@@ -315,7 +315,7 @@ abstract class WidgetsBinding extends BindingBase with GestureBinding, RendererB
/// cause the back button to close dialog boxes, return from modal /// cause the back button to close dialog boxes, return from modal
/// pages, and so forth. /// pages, and so forth.
Future<Null> handlePopRoute() async { Future<Null> handlePopRoute() async {
for (WidgetsBindingObserver observer in new List<WidgetsBindingObserver>.from(_observers)) { for (WidgetsBindingObserver observer in new List<WidgetsBindingObserver>.from(_observers)) {
if (await observer.didPopRoute()) if (await observer.didPopRoute())
return; return;
} }
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'framework.dart'; import 'framework.dart';
import 'routes.dart'; import 'navigator.dart';
import 'will_pop_scope.dart'; import 'will_pop_scope.dart';
/// An optional container for grouping together multiple form field widgets /// An optional container for grouping together multiple form field widgets
...@@ -55,6 +55,11 @@ class Form extends StatefulWidget { ...@@ -55,6 +55,11 @@ class Form extends StatefulWidget {
/// ///
/// If the callback returns a Future that resolves to false, the form's route /// If the callback returns a Future that resolves to false, the form's route
/// will not be popped. /// will not be popped.
///
/// See also:
///
/// * [WillPopScope], another widget that provides a way to intercept the
/// back button.
final WillPopCallback onWillPop; final WillPopCallback onWillPop;
@override @override
......
...@@ -14,9 +14,41 @@ import 'focus_manager.dart'; ...@@ -14,9 +14,41 @@ import 'focus_manager.dart';
import 'focus_scope.dart'; import 'focus_scope.dart';
import 'framework.dart'; import 'framework.dart';
import 'overlay.dart'; import 'overlay.dart';
import 'routes.dart';
import 'ticker_provider.dart'; import 'ticker_provider.dart';
/// Indicates whether the current route should be popped.
///
/// Used as the return value for [Route.willPop].
///
/// See also:
///
/// * [WillPopScope], a widget that hooks into the route's [Route.willPop]
/// mechanism.
enum RoutePopDisposition {
/// Pop the route.
///
/// If [Route.willPop] returns [pop] then the back button will actually pop
/// the current route.
pop,
/// Do not pop the route.
///
/// If [Route.willPop] returns [doNotPop] then the back button will be ignored.
doNotPop,
/// Delegate this to the next level of navigation.
///
/// If [Route.willPop] return [bubble] then the back button will be handled
/// by the [SystemNavigator], which will usually close the application.
bubble,
}
/// Signature for a callback that verifies that it's OK to call [Navigator.pop].
///
/// Used by [Form.onWillPop], [ModalRoute.addScopedWillPopCallback],
/// [ModalRoute.removeScopedWillPopCallback], and [WillPopScope].
typedef Future<bool> WillPopCallback();
/// An abstraction for an entry managed by a [Navigator]. /// An abstraction for an entry managed by a [Navigator].
/// ///
/// This class defines an abstract interface between the navigator and the /// This class defines an abstract interface between the navigator and the
...@@ -79,7 +111,10 @@ abstract class Route<T> { ...@@ -79,7 +111,10 @@ abstract class Route<T> {
/// ///
/// See also: /// See also:
/// ///
/// * [Form], which provides a [Form.onWillPop] callback that uses this mechanism. /// * [Form], which provides a [Form.onWillPop] callback that uses this
/// mechanism.
/// * [WillPopScope], another widget that provides a way to intercept the
/// back button.
Future<RoutePopDisposition> willPop() async { Future<RoutePopDisposition> willPop() async {
return isFirst ? RoutePopDisposition.bubble : RoutePopDisposition.pop; return isFirst ? RoutePopDisposition.bubble : RoutePopDisposition.pop;
} }
...@@ -1157,10 +1192,12 @@ class NavigatorState extends State<Navigator> with TickerProviderStateMixin { ...@@ -1157,10 +1192,12 @@ class NavigatorState extends State<Navigator> with TickerProviderStateMixin {
/// ///
/// See also: /// See also:
/// ///
/// * [Form], which provides a [Form.onWillPop] callback that enables the form /// * [Form], which provides a [Form.onWillPop] callback that enables the form
/// to veto a [maybePop] initiated by the app's back button. /// to veto a [maybePop] initiated by the app's back button.
/// * [ModalRoute], which has as a [ModalRoute.willPop] method that can be /// * [WillPopScope], a widget that hooks into the route's [Route.willPop]
/// defined by a list of [WillPopCallback]s. /// mechanism.
/// * [ModalRoute], which has as a [ModalRoute.willPop] method that can be
/// defined by a list of [WillPopCallback]s.
Future<bool> maybePop([dynamic result]) async { Future<bool> maybePop([dynamic result]) async {
final Route<dynamic> route = _history.last; final Route<dynamic> route = _history.last;
assert(route._navigator == this); assert(route._navigator == this);
......
...@@ -386,34 +386,6 @@ class _ModalScopeStatus extends InheritedWidget { ...@@ -386,34 +386,6 @@ class _ModalScopeStatus extends InheritedWidget {
} }
} }
/// Indicates whether the current route should be popped.
///
/// Used as the return value for [Route.willPop].
enum RoutePopDisposition {
/// Pop the route.
///
/// If [Route.willPop] returns [pop] then the back button will actually pop
/// the current route.
pop,
/// Do not pop the route.
///
/// If [Route.willPop] returns [doNotPop] then the back button will be ignored.
doNotPop,
/// Delegate this to the next level of navigation.
///
/// If [Route.willPop] return [bubble] then the back button will be handled
/// by the [SystemNavigator], which will usually close the application.
bubble,
}
/// Signature for a callback that verifies that it's OK to call [Navigator.pop].
///
/// Used by [Form.onWillPop], [ModalRoute.addScopedWillPopCallback], and
/// [ModalRoute.removeScopedWillPopCallback].
typedef Future<bool> WillPopCallback();
class _ModalScope extends StatefulWidget { class _ModalScope extends StatefulWidget {
const _ModalScope({ const _ModalScope({
Key key, Key key,
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'framework.dart'; import 'framework.dart';
import 'navigator.dart';
import 'routes.dart'; import 'routes.dart';
/// Registers a callback to veto attempts by the user to dismiss the enclosing /// Registers a callback to veto attempts by the user to dismiss the enclosing
......
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