From 04860d725647efe0e56b8bdb3676a8dd4e9bfa84 Mon Sep 17 00:00:00 2001 From: Kate Lovett Date: Tue, 19 May 2020 17:52:05 -0700 Subject: [PATCH] Step 1 of 3: Add opt-in fixing Dialog border radius to match Material Spec (#56084) --- packages/flutter/lib/src/material/dialog.dart | 57 +++++++++++++++++-- .../material/pickers/date_picker_dialog.dart | 1 + .../pickers/date_range_picker_dialog.dart | 4 +- .../flutter/lib/src/material/time_picker.dart | 33 ++++++++++- .../flutter/test/material/dialog_test.dart | 4 +- 5 files changed, 88 insertions(+), 11 deletions(-) diff --git a/packages/flutter/lib/src/material/dialog.dart b/packages/flutter/lib/src/material/dialog.dart index 30766883093..b657e934ac3 100644 --- a/packages/flutter/lib/src/material/dialog.dart +++ b/packages/flutter/lib/src/material/dialog.dart @@ -2,9 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// TODO(shihaohong): remove ignoring deprecated member use analysis -// when AlertDialog.scrollable parameter is removed. See -// https://flutter.dev/go/scrollable-alert-dialog for more details. +// TODO(shihaohong-Piinks): remove ignoring deprecated member use analysis +// * when AlertDialog.scrollable parameter is removed. See +// https://flutter.dev/go/scrollable-alert-dialog for more details. +// * when Dialog.useMaterialBorderRadius parameter is removed. // ignore_for_file: deprecated_member_use_from_same_package import 'dart:async'; @@ -55,7 +56,9 @@ class Dialog extends StatelessWidget { this.clipBehavior = Clip.none, this.shape, this.child, + bool useMaterialBorderRadius, }) : assert(clipBehavior != null), + useMaterialBorderRadius = useMaterialBorderRadius ?? false, super(key: key); /// {@template flutter.material.dialog.backgroundColor} @@ -117,7 +120,8 @@ class Dialog extends StatelessWidget { /// /// Defines the dialog's [Material.shape]. /// - /// The default shape is a [RoundedRectangleBorder] with a radius of 2.0. + /// The default shape is a [RoundedRectangleBorder] with a radius of 2.0 + /// (temporarily, set [useMaterialBorderRadius] to match Material guidelines). /// {@endtemplate} final ShapeBorder shape; @@ -126,8 +130,19 @@ class Dialog extends StatelessWidget { /// {@macro flutter.widgets.child} final Widget child; - // TODO(johnsonmh): Update default dialog border radius to 4.0 to match material spec. + /// Indicates whether the [Dialog.shape]'s default [RoundedRectangleBorder] + /// should have a radius of 4.0 pixels to match Material Design, or use the + /// prior default of 2.0 pixels. + @Deprecated( + 'Set useMaterialBorderRadius to `true`. This parameter will be removed and ' + 'was introduced to migrate Dialog to the correct border radius by default. ' + 'This feature was deprecated after v1.18.0.' + ) + final bool useMaterialBorderRadius; + static const RoundedRectangleBorder _defaultDialogShape = + RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4.0))); + static const RoundedRectangleBorder _oldDefaultDialogShape = RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(2.0))); static const double _defaultElevation = 24.0; @@ -151,7 +166,11 @@ class Dialog extends StatelessWidget { child: Material( color: backgroundColor ?? dialogTheme.backgroundColor ?? Theme.of(context).dialogBackgroundColor, elevation: elevation ?? dialogTheme.elevation ?? _defaultElevation, - shape: shape ?? dialogTheme.shape ?? _defaultDialogShape, + shape: shape ?? dialogTheme.shape ?? ( + useMaterialBorderRadius ? + _defaultDialogShape : + _oldDefaultDialogShape + ), type: MaterialType.card, clipBehavior: clipBehavior, child: child, @@ -260,8 +279,10 @@ class AlertDialog extends StatelessWidget { this.clipBehavior = Clip.none, this.shape, this.scrollable = false, + bool useMaterialBorderRadius, }) : assert(contentPadding != null), assert(clipBehavior != null), + useMaterialBorderRadius = useMaterialBorderRadius ?? false, super(key: key); /// The (optional) title of the dialog is displayed in a large font at the top @@ -449,6 +470,16 @@ class AlertDialog extends StatelessWidget { ) final bool scrollable; + /// Indicates whether the [Dialog.shape]'s default [RoundedRectangleBorder] + /// should have a radius of 4.0 pixels to match Material Design, or use the + /// prior default of 2.0 pixels. + @Deprecated( + 'Set useMaterialBorderRadius to `true`. This parameter will be removed and ' + 'was introduced to migrate Dialog to the correct border radius by default. ' + 'This feature was deprecated after v1.18.0.' + ) + final bool useMaterialBorderRadius; + @override Widget build(BuildContext context) { assert(debugCheckHasMaterialLocalizations(context)); @@ -560,6 +591,7 @@ class AlertDialog extends StatelessWidget { clipBehavior: clipBehavior, shape: shape, child: dialogChild, + useMaterialBorderRadius: useMaterialBorderRadius, ); } } @@ -719,8 +751,10 @@ class SimpleDialog extends StatelessWidget { this.elevation, this.semanticLabel, this.shape, + bool useMaterialBorderRadius, }) : assert(titlePadding != null), assert(contentPadding != null), + useMaterialBorderRadius = useMaterialBorderRadius ?? false, super(key: key); /// The (optional) title of the dialog is displayed in a large font at the top @@ -789,6 +823,16 @@ class SimpleDialog extends StatelessWidget { /// {@macro flutter.material.dialog.shape} final ShapeBorder shape; + /// Indicates whether the [Dialog.shape]'s default [RoundedRectangleBorder] + /// should have a radius of 4.0 pixels to match Material Design, or use the + /// prior default of 2.0 pixels. + @Deprecated( + 'Set useMaterialBorderRadius to `true`. This parameter will be removed and ' + 'was introduced to migrate Dialog to the correct border radius by default. ' + 'This feature was deprecated after v1.18.0.' + ) + final bool useMaterialBorderRadius; + @override Widget build(BuildContext context) { assert(debugCheckHasMaterialLocalizations(context)); @@ -848,6 +892,7 @@ class SimpleDialog extends StatelessWidget { elevation: elevation, shape: shape, child: dialogChild, + useMaterialBorderRadius: useMaterialBorderRadius, ); } } diff --git a/packages/flutter/lib/src/material/pickers/date_picker_dialog.dart b/packages/flutter/lib/src/material/pickers/date_picker_dialog.dart index 4ce0992c02c..85c38caf83c 100644 --- a/packages/flutter/lib/src/material/pickers/date_picker_dialog.dart +++ b/packages/flutter/lib/src/material/pickers/date_picker_dialog.dart @@ -503,6 +503,7 @@ class _DatePickerDialogState extends State<_DatePickerDialog> { ), ), insetPadding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 24.0), + // TODO(Piinks): remove once border radius migration is complete // The default dialog shape is radius 2 rounded rect, but the spec has // been updated to 4, so we will use that here for the Date Picker, but // only if there isn't one provided in the theme. diff --git a/packages/flutter/lib/src/material/pickers/date_range_picker_dialog.dart b/packages/flutter/lib/src/material/pickers/date_range_picker_dialog.dart index aa8f9919ab6..5c88434dd2e 100644 --- a/packages/flutter/lib/src/material/pickers/date_range_picker_dialog.dart +++ b/packages/flutter/lib/src/material/pickers/date_range_picker_dialog.dart @@ -407,9 +407,7 @@ class _DateRangePickerDialogState extends State<_DateRangePickerDialog> { final DialogTheme dialogTheme = Theme.of(context).dialogTheme; size = orientation == Orientation.portrait ? _inputPortraitDialogSize : _inputLandscapeDialogSize; insetPadding = const EdgeInsets.symmetric(horizontal: 16.0, vertical: 24.0); - // The default dialog shape is radius 2 rounded rect, but the spec has - // been updated to 4, so we will use that here for the Input Date Range - // Picker, but only if there isn't one provided in the theme. + // TODO(Piinks): remove once border radius migration is complete shape = dialogTheme.shape ?? const RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(4.0)) ); diff --git a/packages/flutter/lib/src/material/time_picker.dart b/packages/flutter/lib/src/material/time_picker.dart index 066a1431c85..3b705c19250 100644 --- a/packages/flutter/lib/src/material/time_picker.dart +++ b/packages/flutter/lib/src/material/time_picker.dart @@ -23,6 +23,10 @@ import 'theme.dart'; import 'theme_data.dart'; import 'time.dart'; +// TODO(Piinks): remove ignoring deprecated member use analysis +// * when Dialog.useMaterialBorderRadius parameter is removed. +// ignore_for_file: deprecated_member_use_from_same_package + // Examples can assume: // BuildContext context; @@ -1501,12 +1505,24 @@ class _TimePickerDialog extends StatefulWidget { const _TimePickerDialog({ Key key, @required this.initialTime, + bool useMaterialBorderRadius, }) : assert(initialTime != null), + useMaterialBorderRadius = useMaterialBorderRadius ?? false, super(key: key); /// The time initially selected when the dialog is shown. final TimeOfDay initialTime; + /// Indicates whether the [Dialog.shape]'s default [RoundedRectangleBorder] + /// should have a radius of 4.0 pixels to match Material Design, or use the + /// prior default of 2.0 pixels. + @Deprecated( + 'Set useMaterialBorderRadius to `true`. This parameter will be removed and ' + 'was introduced to migrate Dialog to the correct border radius by default. ' + 'This feature was deprecated after v1.18.0.' + ) + final bool useMaterialBorderRadius; + @override _TimePickerDialogState createState() => _TimePickerDialogState(); } @@ -1650,6 +1666,7 @@ class _TimePickerDialogState extends State<_TimePickerDialog> { ); final Dialog dialog = Dialog( + useMaterialBorderRadius: widget.useMaterialBorderRadius, child: OrientationBuilder( builder: (BuildContext context, Orientation orientation) { final Widget header = _TimePickerHeader( @@ -1744,6 +1761,11 @@ class _TimePickerDialogState extends State<_TimePickerDialog> { /// The returned Future resolves to the time selected by the user when the user /// closes the dialog. If the user cancels the dialog, null is returned. /// +/// The [useMaterialBorderRadius] parameter specifies whether th default +/// [Dialog.shape] of the time picker, a [RoundedRectangleBorder], should have a +/// radius of 4.0 pixels to match Material Design, or use the prior default of +/// 2.0 pixels. +/// /// {@tool snippet} /// Show a dialog with [initialTime] equal to the current time. /// @@ -1806,13 +1828,22 @@ Future showTimePicker({ TransitionBuilder builder, bool useRootNavigator = true, RouteSettings routeSettings, + @Deprecated( + 'Set useMaterialBorderRadius to `true`. This parameter will be removed and ' + 'was introduced to migrate Dialog to the correct border radius by default. ' + 'This feature was deprecated after v1.18.0.' + ) + bool useMaterialBorderRadius, }) async { assert(context != null); assert(initialTime != null); assert(useRootNavigator != null); assert(debugCheckHasMaterialLocalizations(context)); - final Widget dialog = _TimePickerDialog(initialTime: initialTime); + final Widget dialog = _TimePickerDialog( + initialTime: initialTime, + useMaterialBorderRadius: useMaterialBorderRadius ?? false, + ); return await showDialog( context: context, useRootNavigator: useRootNavigator, diff --git a/packages/flutter/test/material/dialog_test.dart b/packages/flutter/test/material/dialog_test.dart index 9d579bbfce3..19876c7f2b6 100644 --- a/packages/flutter/test/material/dialog_test.dart +++ b/packages/flutter/test/material/dialog_test.dart @@ -44,7 +44,7 @@ RenderParagraph _getTextRenderObjectFromDialog(WidgetTester tester, String text) return tester.element(find.descendant(of: find.byType(AlertDialog), matching: find.text(text))).renderObject as RenderParagraph; } -const ShapeBorder _defaultDialogShape = RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(2.0))); +const ShapeBorder _defaultDialogShape = RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4.0))); void main() { testWidgets('Dialog is scrollable', (WidgetTester tester) async { @@ -94,6 +94,7 @@ void main() { title: Text('Title'), content: Text('Y'), actions: [ ], + useMaterialBorderRadius: true, ); await tester.pumpWidget(_buildAppWithDialog(dialog, theme: ThemeData(brightness: Brightness.dark))); @@ -189,6 +190,7 @@ void main() { const AlertDialog dialog = AlertDialog( actions: [ ], shape: null, + useMaterialBorderRadius: true, ); await tester.pumpWidget(_buildAppWithDialog(dialog));