Unverified Commit 231170a7 authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

Replace child parameter with builder on showDialog (#15303)

* replace child parameter with builder on showDialog

* change builder parameter to WidgetBuilder

* mark child as deprecated and expand documentation to cover this and how builder should be used

* tidy comments and address some feedback

* phrasing

* move space to prev line and add //ignore comments for deprecated member use

* address comments and fix it's its

* update code samples

* adds semicolon to code snippets
parent 9a8b4602
......@@ -18,8 +18,8 @@ class _CupertinoDialogDemoState extends State<CupertinoDialogDemo> {
void showDemoDialog<T>({ BuildContext context, Widget child }) {
showDialog<T>(
context: context,
child: child,
barrierDismissible: false,
builder: (BuildContext context) => child,
)
.then<Null>((T value) { // The value passed to Navigator.pop() or null.
if (value != null) {
......
......@@ -68,7 +68,7 @@ class DialogDemoState extends State<DialogDemo> {
void showDemoDialog<T>({ BuildContext context, Widget child }) {
showDialog<T>(
context: context,
child: child,
builder: (BuildContext context) => child,
)
.then<Null>((T value) { // The value passed to Navigator.pop() or null.
if (value != null) {
......
......@@ -233,17 +233,19 @@ class _DrawerDemoState extends State<DrawerDemo> with TickerProviderStateMixin {
void _onOtherAccountsTap(BuildContext context) {
showDialog<Null>(
context: context,
child: new AlertDialog(
title: const Text('Account switching not implemented.'),
actions: <Widget>[
new FlatButton(
child: const Text('OK'),
onPressed: () {
Navigator.of(context).pop();
},
),
],
),
builder: (BuildContext context) {
return new AlertDialog(
title: const Text('Account switching not implemented.'),
actions: <Widget>[
new FlatButton(
child: const Text('OK'),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
);
}
}
......@@ -116,26 +116,28 @@ class FullScreenDialogDemoState extends State<FullScreenDialogDemo> {
return await showDialog<bool>(
context: context,
child: new AlertDialog(
content: new Text(
'Discard new event?',
style: dialogTextStyle
),
actions: <Widget>[
new FlatButton(
child: const Text('CANCEL'),
onPressed: () {
Navigator.of(context).pop(false); // Pops the confirmation dialog but not the page.
}
builder: (BuildContext context) {
return new AlertDialog(
content: new Text(
'Discard new event?',
style: dialogTextStyle
),
new FlatButton(
child: const Text('DISCARD'),
onPressed: () {
Navigator.of(context).pop(true); // Returning true to _onWillPop will pop again.
}
)
]
)
actions: <Widget>[
new FlatButton(
child: const Text('CANCEL'),
onPressed: () {
Navigator.of(context).pop(false); // Pops the confirmation dialog but not the page.
}
),
new FlatButton(
child: const Text('DISCARD'),
onPressed: () {
Navigator.of(context).pop(true); // Returning true to _onWillPop will pop again.
}
)
],
);
},
) ?? false;
}
......
......@@ -56,15 +56,19 @@ class _PersistentBottomSheetDemoState extends State<PersistentBottomSheetDemo> {
void _showMessage() {
showDialog<Null>(
context: context,
child: new AlertDialog(
content: const Text('You tapped the floating action button.'),
actions: <Widget>[
new FlatButton(
onPressed: () { Navigator.pop(context); },
child: const Text('OK')
)
]
)
builder: (BuildContext context) {
return new AlertDialog(
content: const Text('You tapped the floating action button.'),
actions: <Widget>[
new FlatButton(
onPressed: () {
Navigator.pop(context);
},
child: const Text('OK')
)
],
);
},
);
}
......
......@@ -85,20 +85,22 @@ class TextFormFieldDemoState extends State<TextFormFieldDemo> {
return await showDialog<bool>(
context: context,
child: new AlertDialog(
title: const Text('This form has errors'),
content: const Text('Really leave this form?'),
actions: <Widget> [
new FlatButton(
child: const Text('YES'),
onPressed: () { Navigator.of(context).pop(true); },
),
new FlatButton(
child: const Text('NO'),
onPressed: () { Navigator.of(context).pop(false); },
),
],
),
builder: (BuildContext context) {
return new AlertDialog(
title: const Text('This form has errors'),
content: const Text('Really leave this form?'),
actions: <Widget> [
new FlatButton(
child: const Text('YES'),
onPressed: () { Navigator.of(context).pop(true); },
),
new FlatButton(
child: const Text('NO'),
onPressed: () { Navigator.of(context).pop(false); },
),
],
);
},
) ?? false;
}
......
......@@ -41,13 +41,13 @@ class UpdaterState extends State<Updater> {
final String updateUrl = await widget.updateUrlFetcher();
if (updateUrl != null) {
final bool wantsUpdate = await showDialog(context: context, child: _buildDialog());
final bool wantsUpdate = await showDialog(context: context, builder: _buildDialog);
if (wantsUpdate != null && wantsUpdate)
launch(updateUrl);
}
}
Widget _buildDialog() {
Widget _buildDialog(BuildContext _) {
final ThemeData theme = Theme.of(context);
final TextStyle dialogTextStyle =
theme.textTheme.subhead.copyWith(color: theme.textTheme.caption.color);
......
......@@ -95,7 +95,7 @@ class StockHomeState extends State<StockHome> {
case _StockMenuItem.refresh:
showDialog<Null>(
context: context,
child: new _NotImplementedDialog()
builder: (BuildContext context) => new _NotImplementedDialog(),
);
break;
case _StockMenuItem.speedUp:
......
......@@ -67,24 +67,26 @@ class StockSettingsState extends State<StockSettings> {
case StockMode.pessimistic:
showDialog<bool>(
context: context,
child: new AlertDialog(
title: const Text('Change mode?'),
content: const Text('Optimistic mode means everything is awesome. Are you sure you can handle that?'),
actions: <Widget>[
new FlatButton(
child: const Text('NO THANKS'),
onPressed: () {
Navigator.pop(context, false);
}
),
new FlatButton(
child: const Text('AGREE'),
onPressed: () {
Navigator.pop(context, true);
}
),
]
)
builder: (BuildContext context) {
return new AlertDialog(
title: const Text('Change mode?'),
content: const Text('Optimistic mode means everything is awesome. Are you sure you can handle that?'),
actions: <Widget>[
new FlatButton(
child: const Text('NO THANKS'),
onPressed: () {
Navigator.pop(context, false);
}
),
new FlatButton(
child: const Text('AGREE'),
onPressed: () {
Navigator.pop(context, true);
}
),
],
);
},
).then<void>(_handleOptimismChanged);
break;
}
......
......@@ -153,13 +153,15 @@ void showAboutDialog({
}) {
showDialog<Null>(
context: context,
child: new AboutDialog(
applicationName: applicationName,
applicationVersion: applicationVersion,
applicationIcon: applicationIcon,
applicationLegalese: applicationLegalese,
children: children
)
builder: (BuildContext context) {
return new AboutDialog(
applicationName: applicationName,
applicationVersion: applicationVersion,
applicationIcon: applicationIcon,
applicationLegalese: applicationLegalese,
children: children,
);
}
);
}
......
......@@ -1042,6 +1042,6 @@ Future<DateTime> showDatePicker({
return await showDialog<DateTime>(
context: context,
child: child,
builder: (BuildContext context) => child,
);
}
......@@ -96,25 +96,27 @@ class Dialog extends StatelessWidget {
/// return showDialog<Null>(
/// context: context,
/// barrierDismissible: false, // user must tap button!
/// child: new AlertDialog(
/// title: new Text('Rewind and remember'),
/// content: new SingleChildScrollView(
/// child: new ListBody(
/// children: <Widget>[
/// new Text('You will never be satisfied.'),
/// new Text('You\’re like me. I’m never satisfied.'),
/// ],
/// builder: (BuildContext context) {
/// return new AlertDialog(
/// title: new Text('Rewind and remember'),
/// content: new SingleChildScrollView(
/// child: new ListBody(
/// children: <Widget>[
/// new Text('You will never be satisfied.'),
/// new Text('You\’re like me. I’m never satisfied.'),
/// ],
/// ),
/// ),
/// ),
/// actions: <Widget>[
/// new FlatButton(
/// child: new Text('Regret'),
/// onPressed: () {
/// Navigator.of(context).pop();
/// },
/// ),
/// ],
/// ),
/// actions: <Widget>[
/// new FlatButton(
/// child: new Text('Regret'),
/// onPressed: () {
/// Navigator.of(context).pop();
/// },
/// ),
/// ],
/// );
/// },
/// );
/// }
/// ```
......@@ -301,19 +303,21 @@ class SimpleDialogOption extends StatelessWidget {
/// Future<Null> _askedToLead() async {
/// switch (await showDialog<Department>(
/// context: context,
/// child: new SimpleDialog(
/// title: const Text('Select assignment'),
/// children: <Widget>[
/// new SimpleDialogOption(
/// onPressed: () { Navigator.pop(context, Department.treasury); },
/// child: const Text('Treasury department'),
/// ),
/// new SimpleDialogOption(
/// onPressed: () { Navigator.pop(context, Department.state); },
/// child: const Text('State department'),
/// ),
/// ],
/// ),
/// builder: (BuildContext context) {
/// return new SimpleDialog(
/// title: const Text('Select assignment'),
/// children: <Widget>[
/// new SimpleDialogOption(
/// onPressed: () { Navigator.pop(context, Department.treasury); },
/// child: const Text('Treasury department'),
/// ),
/// new SimpleDialogOption(
/// onPressed: () { Navigator.pop(context, Department.state); },
/// child: const Text('State department'),
/// ),
/// ],
/// );
/// }
/// )) {
/// case Department.treasury:
/// // Let's go.
......@@ -457,13 +461,18 @@ class _DialogRoute<T> extends PopupRoute<T> {
/// Displays a dialog above the current contents of the app.
///
/// This function typically receives a [Dialog] widget as its child argument.
/// Content below the dialog is dimmed with a [ModalBarrier].
/// This function takes a `builder` which typically builds a [Dialog] widget.
/// Content below the dialog is dimmed with a [ModalBarrier]. This widget does
/// not share a context with the location that `showDialog` is originally
/// called from. Use a [StatefulBuilder] or a custom [StatefulWidget] if the
/// dialog needs to update dynamically.
///
/// The `context` argument is used to look up the [Navigator] and [Theme] for
/// the dialog. It is only used when the method is called. Its corresponding
/// widget can be safely removed from the tree before the dialog is closed.
///
/// The `child` argument is deprecated, and should be replaced with `builder`.
///
/// Returns a [Future] that resolves to the value (if any) that was passed to
/// [Navigator.pop] when the dialog was closed.
///
......@@ -481,10 +490,16 @@ class _DialogRoute<T> extends PopupRoute<T> {
Future<T> showDialog<T>({
@required BuildContext context,
bool barrierDismissible: true,
@required Widget child,
@Deprecated(
'Instead of using the "child" argument, return the child from a closure '
'provided to the "builder" argument. This will ensure that the BuildContext '
'is appropriate for widgets built in the dialog.'
) Widget child,
WidgetBuilder builder,
}) {
assert(child == null || builder == null); // ignore: deprecated_member_use
return Navigator.of(context, rootNavigator: true).push(new _DialogRoute<T>(
child: child,
child: child ?? new Builder(builder: builder), // ignore: deprecated_member_use
theme: Theme.of(context, shadowThemeOnly: true),
barrierDismissible: barrierDismissible,
barrierLabel: MaterialLocalizations.of(context).modalBarrierDismissLabel,
......
......@@ -1645,7 +1645,7 @@ Future<TimeOfDay> showTimePicker({
return await showDialog<TimeOfDay>(
context: context,
child: new _TimePickerDialog(initialTime: initialTime),
builder: (BuildContext context) => new _TimePickerDialog(initialTime: initialTime),
);
}
......
......@@ -19,23 +19,25 @@ void main() {
onPressed: () {
showDialog<Null>(
context: context,
child: new CupertinoAlertDialog(
title: const Text('The title'),
content: const Text('The content'),
actions: <Widget>[
const CupertinoDialogAction(
child: const Text('Cancel'),
),
new CupertinoDialogAction(
isDestructiveAction: true,
onPressed: () {
didDelete = true;
Navigator.pop(context);
},
child: const Text('Delete'),
),
],
),
builder: (BuildContext context) {
return new CupertinoAlertDialog(
title: const Text('The title'),
content: const Text('The content'),
actions: <Widget>[
const CupertinoDialogAction(
child: const Text('Cancel'),
),
new CupertinoDialogAction(
isDestructiveAction: true,
onPressed: () {
didDelete = true;
Navigator.pop(context);
},
child: const Text('Delete'),
),
],
);
},
);
},
child: const Text('Go'),
......@@ -110,7 +112,7 @@ void main() {
onPressed: () {
showDialog<Null>(
context: context,
child: new Builder(builder: (BuildContext context) {
builder: (BuildContext context) {
return new MediaQuery(
data: MediaQuery.of(context).copyWith(textScaleFactor: 3.0),
child: new CupertinoAlertDialog(
......@@ -128,7 +130,7 @@ void main() {
scrollController: scrollController,
),
);
}),
},
);
},
child: const Text('Go'),
......
......@@ -23,21 +23,23 @@ void main() {
onPressed: () {
showDialog<Null>(
context: context,
child: new AlertDialog(
content: new Container(
height: 5000.0,
width: 300.0,
color: Colors.green[500],
),
actions: <Widget>[
new FlatButton(
onPressed: () {
didPressOk = true;
},
child: const Text('OK')
)
]
)
builder: (BuildContext context) {
return new AlertDialog(
content: new Container(
height: 5000.0,
width: 300.0,
color: Colors.green[500],
),
actions: <Widget>[
new FlatButton(
onPressed: () {
didPressOk = true;
},
child: const Text('OK')
)
],
);
},
);
}
)
......@@ -71,11 +73,13 @@ void main() {
onPressed: () {
showDialog<Null>(
context: context,
child: const AlertDialog(
title: const Text('Title'),
content: const Text('Y'),
actions: const <Widget>[ ],
),
builder: (BuildContext context) {
return const AlertDialog(
title: const Text('Title'),
content: const Text('Y'),
actions: const <Widget>[ ],
);
},
);
},
),
......@@ -116,20 +120,22 @@ void main() {
final Future<int> result = showDialog(
context: context,
child: new SimpleDialog(
title: const Text('Title'),
children: <Widget>[
new SimpleDialogOption(
onPressed: () {
Navigator.pop(context, 42);
},
child: const Text('First option'),
),
const SimpleDialogOption(
child: const Text('Second option'),
),
],
),
builder: (BuildContext context) {
return new SimpleDialog(
title: const Text('Title'),
children: <Widget>[
new SimpleDialogOption(
onPressed: () {
Navigator.pop(context, 42);
},
child: const Text('First option'),
),
const SimpleDialogOption(
child: const Text('Second option'),
),
],
);
},
);
await tester.pumpAndSettle(const Duration(seconds: 1));
......@@ -157,12 +163,14 @@ void main() {
showDialog<Null>(
context: context,
child: new Container(
width: 100.0,
height: 100.0,
alignment: Alignment.center,
child: const Text('Dialog1'),
),
builder: (BuildContext context) {
return new Container(
width: 100.0,
height: 100.0,
alignment: Alignment.center,
child: const Text('Dialog1'),
);
},
);
await tester.pumpAndSettle(const Duration(seconds: 1));
......@@ -177,12 +185,14 @@ void main() {
showDialog<Null>(
context: context,
barrierDismissible: false,
child: new Container(
width: 100.0,
height: 100.0,
alignment: Alignment.center,
child: const Text('Dialog2'),
),
builder: (BuildContext context) {
return new Container(
width: 100.0,
height: 100.0,
alignment: Alignment.center,
child: const Text('Dialog2'),
);
},
);
await tester.pumpAndSettle(const Duration(seconds: 1));
......@@ -219,7 +229,9 @@ void main() {
const String alertText = 'A button in an overlay alert';
showDialog<Null>(
context: context,
child: const AlertDialog(title: const Text(alertText)),
builder: (BuildContext context) {
return const AlertDialog(title: const Text(alertText));
},
);
await tester.pumpAndSettle(const Duration(seconds: 1));
......@@ -260,12 +272,10 @@ void main() {
showDialog<Null>(
context: outerContext,
barrierDismissible: false,
child: new Builder(
builder: (BuildContext context) {
dialogContext = context;
return new Container();
},
),
builder: (BuildContext context) {
dialogContext = context;
return new Container();
},
);
await tester.pump();
......
......@@ -110,7 +110,7 @@ void main() {
showDialog<Null>(
context: context,
child: const SimpleDialog(title: const Text('Dialog')),
builder: (BuildContext context) => const SimpleDialog(title: const Text('Dialog')),
);
await tester.pump();
......
......@@ -200,7 +200,7 @@ void main() {
onPressed: () {
showDialog<Null>(
context: context,
child: const Text('dialog'),
builder: (BuildContext context) => const Text('dialog'),
);
},
child: const Text('SHOW'),
......@@ -232,12 +232,14 @@ void main() {
onTap: () {
showDialog<Null>(
context: context,
child: const Scaffold(
body: const SizedBox(
width: 200.0,
height: 200.0,
),
)
builder: (BuildContext context) {
return const Scaffold(
body: const SizedBox(
width: 200.0,
height: 200.0,
),
);
},
);
},
child: const Text('SHOW'),
......
......@@ -86,7 +86,7 @@ void main() {
onPressed: () {
showDialog<Null>(
context: context,
child: new SamplePage(),
builder: (BuildContext context) => new SamplePage(),
);
},
),
......@@ -185,18 +185,20 @@ void main() {
Future<bool> showYesNoAlert(BuildContext context) {
return showDialog<bool>(
context: context,
child: new AlertDialog(
actions: <Widget> [
new FlatButton(
child: const Text('YES'),
onPressed: () { Navigator.of(context).pop(true); },
),
new FlatButton(
child: const Text('NO'),
onPressed: () { Navigator.of(context).pop(false); },
),
],
),
builder: (BuildContext context) {
return new AlertDialog(
actions: <Widget> [
new FlatButton(
child: const Text('YES'),
onPressed: () { Navigator.of(context).pop(true); },
),
new FlatButton(
child: const Text('NO'),
onPressed: () { Navigator.of(context).pop(false); },
),
],
);
},
);
}
......
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