Unverified Commit 62e436f0 authored by Shi-Hao Hong's avatar Shi-Hao Hong Committed by GitHub

Implement AlertDialog.actionsPadding and AlertDialog.buttonPadding (#47709)

* Implement AlertDialog.actionsPadding and AlertDialog.buttonPadding
parent 7b69d137
......@@ -221,6 +221,8 @@ class AlertDialog extends StatelessWidget {
this.contentPadding = const EdgeInsets.fromLTRB(24.0, 20.0, 24.0, 24.0),
this.contentTextStyle,
this.actions,
this.actionsPadding = EdgeInsets.zero,
this.buttonPadding,
this.backgroundColor,
this.elevation,
this.semanticLabel,
......@@ -289,6 +291,42 @@ class AlertDialog extends StatelessWidget {
/// from the [actions].
final List<Widget> actions;
/// Padding around the the set of [actions] at the bottom of the dialog.
///
/// Typically used to provide padding to the button bar between the button bar
/// and the edges of the dialog.
///
/// If are no [actions], then no padding will be included. The padding around
/// the button bar defaults to zero. It is also important to note that
/// [buttonPadding] may contribute to the padding on the edges of [actions] as
/// well.
///
/// {@tool sample}
/// This is an example of a set of actions aligned with the content widget.
/// ```dart
/// AlertDialog(
/// title: Text('Title'),
/// content: Container(width: 200, height: 200, color: Colors.green),
/// actions: <Widget>[
/// RaisedButton(onPressed: () {}, child: Text('Button 1')),
/// RaisedButton(onPressed: () {}, child: Text('Button 2')),
/// ],
/// actionsPadding: EdgeInsets.symmetric(horizontal: 8.0),
/// )
/// ```
/// {@end-tool}
final EdgeInsetsGeometry actionsPadding;
/// The padding that surrounds each button in [actions].
///
/// This is different from [actionsPadding], which defines the padding
/// between the entire button bar and the edges of the dialog.
///
/// If this property is null, then it will use the surrounding
/// [ButtonBarTheme.buttonPadding]. If that is null, it will default to
/// 8.0 logical pixels on the left and right.
final EdgeInsetsGeometry buttonPadding;
/// {@macro flutter.material.dialog.backgroundColor}
final Color backgroundColor;
......@@ -349,6 +387,7 @@ class AlertDialog extends StatelessWidget {
Widget titleWidget;
Widget contentWidget;
Widget actionsWidget;
if (title != null)
titleWidget = Padding(
padding: titlePadding ?? EdgeInsets.fromLTRB(24.0, 24.0, 24.0, content == null ? 20.0 : 0.0),
......@@ -371,6 +410,15 @@ class AlertDialog extends StatelessWidget {
),
);
if (actions != null)
actionsWidget = Padding(
padding: actionsPadding,
child: ButtonBar(
buttonPadding: buttonPadding,
children: actions,
),
);
List<Widget> columnChildren;
if (scrollable) {
columnChildren = <Widget>[
......@@ -390,7 +438,7 @@ class AlertDialog extends StatelessWidget {
),
),
if (actions != null)
ButtonBar(children: actions),
actionsWidget,
];
} else {
columnChildren = <Widget>[
......@@ -399,7 +447,7 @@ class AlertDialog extends StatelessWidget {
if (content != null)
Flexible(child: contentWidget),
if (actions != null)
ButtonBar(children: actions),
actionsWidget,
];
}
......
......@@ -13,26 +13,26 @@ import '../widgets/semantics_tester.dart';
MaterialApp _appWithAlertDialog(WidgetTester tester, AlertDialog dialog, { ThemeData theme }) {
return MaterialApp(
theme: theme,
home: Material(
child: Builder(
builder: (BuildContext context) {
return Center(
child: RaisedButton(
child: const Text('X'),
onPressed: () {
showDialog<void>(
context: context,
builder: (BuildContext context) {
return dialog;
},
);
},
),
);
}
),
theme: theme,
home: Material(
child: Builder(
builder: (BuildContext context) {
return Center(
child: RaisedButton(
child: const Text('X'),
onPressed: () {
showDialog<void>(
context: context,
builder: (BuildContext context) {
return dialog;
},
);
},
),
);
}
),
),
);
}
......@@ -340,6 +340,197 @@ void main() {
semantics.dispose();
});
testWidgets('AlertDialog.actionsPadding defaults', (WidgetTester tester) async {
final AlertDialog dialog = AlertDialog(
title: const Text('title'),
content: const Text('content'),
actions: <Widget>[
RaisedButton(
onPressed: () {},
child: const Text('button'),
),
],
);
await tester.pumpWidget(
_appWithAlertDialog(tester, dialog),
);
await tester.tap(find.text('X'));
await tester.pumpAndSettle();
// The [AlertDialog] is the entire screen, since it also contains the scrim.
// The first [Material] child of [AlertDialog] is the actual dialog
// itself.
final Size dialogSize = tester.getSize(
find.descendant(
of: find.byType(AlertDialog),
matching: find.byType(Material),
).first,
);
final Size actionsSize = tester.getSize(find.byType(ButtonBar));
expect(actionsSize.width, dialogSize.width);
});
testWidgets('AlertDialog.actionsPadding surrounds actions with padding', (WidgetTester tester) async {
final AlertDialog dialog = AlertDialog(
title: const Text('title'),
content: const Text('content'),
actions: <Widget>[
RaisedButton(
onPressed: () {},
child: const Text('button'),
),
],
actionsPadding: const EdgeInsets.all(30.0), // custom padding value
);
await tester.pumpWidget(
_appWithAlertDialog(tester, dialog),
);
await tester.tap(find.text('X'));
await tester.pumpAndSettle();
// The [AlertDialog] is the entire screen, since it also contains the scrim.
// The first [Material] child of [AlertDialog] is the actual dialog
// itself.
final Size dialogSize = tester.getSize(
find.descendant(
of: find.byType(AlertDialog),
matching: find.byType(Material),
).first,
);
final Size actionsSize = tester.getSize(find.byType(ButtonBar));
expect(actionsSize.width, dialogSize.width - (30.0 * 2));
});
testWidgets('AlertDialog.buttonPadding defaults', (WidgetTester tester) async {
final GlobalKey key1 = GlobalKey();
final GlobalKey key2 = GlobalKey();
final AlertDialog dialog = AlertDialog(
title: const Text('title'),
content: const Text('content'),
actions: <Widget>[
RaisedButton(
key: key1,
onPressed: () {},
child: const Text('button 1'),
),
RaisedButton(
key: key2,
onPressed: () {},
child: const Text('button 2'),
),
],
);
await tester.pumpWidget(
_appWithAlertDialog(tester, dialog),
);
await tester.tap(find.text('X'));
await tester.pumpAndSettle();
// Padding between both buttons
expect(
tester.getBottomLeft(find.byKey(key2)).dx,
tester.getBottomRight(find.byKey(key1)).dx + 8.0,
);
// Padding between button and edges of the button bar
// First button
expect(
tester.getTopRight(find.byKey(key1)).dy,
tester.getTopRight(find.byType(ButtonBar)).dy + 8.0,
); // top
expect(
tester.getBottomRight(find.byKey(key1)).dy,
tester.getBottomRight(find.byType(ButtonBar)).dy - 8.0,
); // bottom
// Second button
expect(
tester.getTopRight(find.byKey(key2)).dy,
tester.getTopRight(find.byType(ButtonBar)).dy + 8.0,
); // top
expect(
tester.getBottomRight(find.byKey(key2)).dy,
tester.getBottomRight(find.byType(ButtonBar)).dy - 8.0,
); // bottom
expect(
tester.getBottomRight(find.byKey(key2)).dx,
tester.getBottomRight(find.byType(ButtonBar)).dx - 8.0,
); // right
});
testWidgets('AlertDialog.buttonPadding custom values', (WidgetTester tester) async {
final GlobalKey key1 = GlobalKey();
final GlobalKey key2 = GlobalKey();
final AlertDialog dialog = AlertDialog(
title: const Text('title'),
content: const Text('content'),
actions: <Widget>[
RaisedButton(
key: key1,
onPressed: () {},
child: const Text('button 1'),
),
RaisedButton(
key: key2,
onPressed: () {},
child: const Text('button 2'),
),
],
buttonPadding: const EdgeInsets.only(
left: 10.0,
right: 20.0,
),
);
await tester.pumpWidget(
_appWithAlertDialog(tester, dialog),
);
await tester.tap(find.text('X'));
await tester.pumpAndSettle();
// Padding between both buttons
expect(
tester.getBottomLeft(find.byKey(key2)).dx,
tester.getBottomRight(find.byKey(key1)).dx + ((10.0 + 20.0) / 2),
);
// Padding between button and edges of the button bar
// First button
expect(
tester.getTopRight(find.byKey(key1)).dy,
tester.getTopRight(find.byType(ButtonBar)).dy + ((10.0 + 20.0) / 2),
); // top
expect(
tester.getBottomRight(find.byKey(key1)).dy,
tester.getBottomRight(find.byType(ButtonBar)).dy - ((10.0 + 20.0) / 2),
); // bottom
// Second button
expect(
tester.getTopRight(find.byKey(key2)).dy,
tester.getTopRight(find.byType(ButtonBar)).dy + ((10.0 + 20.0) / 2),
); // top
expect(
tester.getBottomRight(find.byKey(key2)).dy,
tester.getBottomRight(find.byType(ButtonBar)).dy - ((10.0 + 20.0) / 2),
); // bottom
expect(
tester.getBottomRight(find.byKey(key2)).dx,
tester.getBottomRight(find.byType(ButtonBar)).dx - ((10.0 + 20.0) / 2),
); // right
});
testWidgets('Dialogs removes MediaQuery padding and view insets', (WidgetTester tester) async {
BuildContext outerContext;
BuildContext routeContext;
......
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