1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/foundation.dart';
import 'framework.dart';
import 'navigator.dart';
import 'routes.dart';
/// Registers a callback to veto attempts by the user to dismiss the enclosing
/// [ModalRoute].
///
/// See also:
///
/// * [ModalRoute.addScopedWillPopCallback] and [ModalRoute.removeScopedWillPopCallback],
/// which this widget uses to register and unregister [onWillPop].
class WillPopScope extends StatefulWidget {
/// Creates a widget that registers a callback to veto attempts by the user to
/// dismiss the enclosing [ModalRoute].
///
/// The [child] argument must not be null.
const WillPopScope({
Key key,
@required this.child,
@required this.onWillPop,
}) : assert(child != null),
super(key: key);
/// The widget below this widget in the tree.
final Widget child;
/// Called to veto attempts by the user to dismiss the enclosing [ModalRoute].
///
/// If the callback returns a Future that resolves to false, the enclosing
/// route will not be popped.
final WillPopCallback onWillPop;
@override
_WillPopScopeState createState() => new _WillPopScopeState();
}
class _WillPopScopeState extends State<WillPopScope> {
ModalRoute<dynamic> _route;
@override
void didChangeDependencies() {
super.didChangeDependencies();
if (widget.onWillPop != null)
_route?.removeScopedWillPopCallback(widget.onWillPop);
_route = ModalRoute.of(context);
if (widget.onWillPop != null)
_route?.addScopedWillPopCallback(widget.onWillPop);
}
@override
void didUpdateWidget(WillPopScope oldWidget) {
super.didUpdateWidget(oldWidget);
assert(_route == ModalRoute.of(context));
if (widget.onWillPop != oldWidget.onWillPop && _route != null) {
if (oldWidget.onWillPop != null)
_route.removeScopedWillPopCallback(oldWidget.onWillPop);
if (widget.onWillPop != null)
_route.addScopedWillPopCallback(widget.onWillPop);
}
}
@override
void dispose() {
if (widget.onWillPop != null)
_route?.removeScopedWillPopCallback(widget.onWillPop);
super.dispose();
}
@override
Widget build(BuildContext context) => widget.child;
}