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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
// Copyright 2014 The Flutter 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/widgets.dart';
import 'debug.dart';
import 'icon_button.dart';
import 'icons.dart';
import 'material_localizations.dart';
import 'theme.dart';
/// A "back" icon that's appropriate for the current [TargetPlatform].
///
/// The current platform is determined by querying for the ambient [Theme].
///
/// See also:
///
/// * [BackButton], an [IconButton] with a [BackButtonIcon] that calls
/// [Navigator.maybePop] to return to the previous route.
/// * [IconButton], which is a more general widget for creating buttons
/// with icons.
/// * [Icon], a material design icon.
/// * [ThemeData.platform], which specifies the current platform.
class BackButtonIcon extends StatelessWidget {
/// Creates an icon that shows the appropriate "back" image for
/// the current platform (as obtained from the [Theme]).
const BackButtonIcon({ Key? key }) : super(key: key);
/// Returns the appropriate "back" icon for the given `platform`.
static IconData _getIconData(TargetPlatform platform) {
switch (platform) {
case TargetPlatform.android:
case TargetPlatform.fuchsia:
case TargetPlatform.linux:
case TargetPlatform.windows:
return Icons.arrow_back;
case TargetPlatform.iOS:
case TargetPlatform.macOS:
return Icons.arrow_back_ios;
}
}
@override
Widget build(BuildContext context) => Icon(_getIconData(Theme.of(context).platform));
}
/// A material design back button.
///
/// A [BackButton] is an [IconButton] with a "back" icon appropriate for the
/// current [TargetPlatform]. When pressed, the back button calls
/// [Navigator.maybePop] to return to the previous route unless a custom
/// [onPressed] callback is provided.
///
/// When deciding to display a [BackButton], consider using
/// `ModalRoute.of(context)?.canPop` to check whether the current route can be
/// popped. If that value is false (e.g., because the current route is the
/// initial route), the [BackButton] will not have any effect when pressed,
/// which could frustrate the user.
///
/// Requires one of its ancestors to be a [Material] widget.
///
/// See also:
///
/// * [AppBar], which automatically uses a [BackButton] in its
/// [AppBar.leading] slot when the [Scaffold] has no [Drawer] and the
/// current [Route] is not the [Navigator]'s first route.
/// * [BackButtonIcon], which is useful if you need to create a back button
/// that responds differently to being pressed.
/// * [IconButton], which is a more general widget for creating buttons with
/// icons.
/// * [CloseButton], an alternative which may be more appropriate for leaf
/// node pages in the navigation tree.
class BackButton extends StatelessWidget {
/// Creates an [IconButton] with the appropriate "back" icon for the current
/// target platform.
const BackButton({ Key? key, this.color, this.onPressed }) : super(key: key);
/// The color to use for the icon.
///
/// Defaults to the [IconThemeData.color] specified in the ambient [IconTheme],
/// which usually matches the ambient [Theme]'s [ThemeData.iconTheme].
final Color? color;
/// An override callback to perform instead of the default behavior which is
/// to pop the [Navigator].
///
/// It can, for instance, be used to pop the platform's navigation stack
/// via [SystemNavigator] instead of Flutter's [Navigator] in add-to-app
/// situations.
///
/// Defaults to null.
final VoidCallback? onPressed;
@override
Widget build(BuildContext context) {
assert(debugCheckHasMaterialLocalizations(context));
return IconButton(
icon: const BackButtonIcon(),
color: color,
tooltip: MaterialLocalizations.of(context).backButtonTooltip,
onPressed: () {
if (onPressed != null) {
onPressed!();
} else {
Navigator.maybePop(context);
}
},
);
}
}
/// A material design close button.
///
/// A [CloseButton] is an [IconButton] with a "close" icon. When pressed, the
/// close button calls [Navigator.maybePop] to return to the previous route.
///
/// Use a [CloseButton] instead of a [BackButton] on fullscreen dialogs or
/// pages that may solicit additional actions to close.
///
/// See also:
///
/// * [AppBar], which automatically uses a [CloseButton] in its
/// [AppBar.leading] slot when appropriate.
/// * [BackButton], which is more appropriate for middle nodes in the
/// navigation tree or where pages can be popped instantaneously with
/// no user data consequence.
/// * [IconButton], to create other material design icon buttons.
class CloseButton extends StatelessWidget {
/// Creates a Material Design close button.
const CloseButton({ Key? key, this.color, this.onPressed }) : super(key: key);
/// The color to use for the icon.
///
/// Defaults to the [IconThemeData.color] specified in the ambient [IconTheme],
/// which usually matches the ambient [Theme]'s [ThemeData.iconTheme].
final Color? color;
/// An override callback to perform instead of the default behavior which is
/// to pop the [Navigator].
///
/// It can, for instance, be used to pop the platform's navigation stack
/// via [SystemNavigator] instead of Flutter's [Navigator] in add-to-app
/// situations.
///
/// Defaults to null.
final VoidCallback? onPressed;
@override
Widget build(BuildContext context) {
assert(debugCheckHasMaterialLocalizations(context));
return IconButton(
icon: const Icon(Icons.close),
color: color,
tooltip: MaterialLocalizations.of(context).closeButtonTooltip,
onPressed: () {
if (onPressed != null) {
onPressed!();
} else {
Navigator.maybePop(context);
}
},
);
}
}