From 192c339150bd44074ae3b8f1d92d47a2d9016a45 Mon Sep 17 00:00:00 2001 From: darrenaustin Date: Mon, 1 Aug 2022 00:06:28 -0700 Subject: [PATCH] Revert "Revert "Add shadowColor and surfaceTintColor to Dialog and DialogTheme." (#108621)" This reverts commit 4ed9d9de4d2c1324e8dfa68168efa7b26fb55031. --- .../gen_defaults/lib/dialog_template.dart | 6 +- packages/flutter/lib/src/material/dialog.dart | 86 +++++++++++++++++-- .../lib/src/material/dialog_theme.dart | 18 ++++ .../flutter/test/material/dialog_test.dart | 6 ++ .../test/material/dialog_theme_test.dart | 16 +++- 5 files changed, 120 insertions(+), 12 deletions(-) diff --git a/dev/tools/gen_defaults/lib/dialog_template.dart b/dev/tools/gen_defaults/lib/dialog_template.dart index 6fe11741fdd90..9fad9b7fd2f58 100644 --- a/dev/tools/gen_defaults/lib/dialog_template.dart +++ b/dev/tools/gen_defaults/lib/dialog_template.dart @@ -27,9 +27,11 @@ class _${blockName}DefaultsM3 extends DialogTheme { @override Color? get iconColor => _colors.secondary; - // TODO(darrenaustin): overlay should be handled by Material widget: https://github.com/flutter/flutter/issues/9160 @override - Color? get backgroundColor => ElevationOverlay.colorWithOverlay(${componentColor("md.comp.dialog.container")}, _colors.primary, ${elevation("md.comp.dialog.container")}); + Color? get backgroundColor => ${componentColor("md.comp.dialog.container")}; + + @override + Color? get surfaceTintColor => ${componentColor("md.comp.dialog.container.surface-tint-layer")}; @override TextStyle? get titleTextStyle => ${textStyle("md.comp.dialog.headline")}; diff --git a/packages/flutter/lib/src/material/dialog.dart b/packages/flutter/lib/src/material/dialog.dart index a85dd27d0e1cc..21dd15228f8fc 100644 --- a/packages/flutter/lib/src/material/dialog.dart +++ b/packages/flutter/lib/src/material/dialog.dart @@ -11,7 +11,6 @@ import 'color_scheme.dart'; import 'colors.dart'; import 'debug.dart'; import 'dialog_theme.dart'; -import 'elevation_overlay.dart'; import 'ink_well.dart'; import 'material.dart'; import 'material_localizations.dart'; @@ -46,6 +45,8 @@ class Dialog extends StatelessWidget { super.key, this.backgroundColor, this.elevation, + this.shadowColor, + this.surfaceTintColor, this.insetAnimationDuration = const Duration(milliseconds: 100), this.insetAnimationCurve = Curves.decelerate, this.insetPadding = _defaultInsetPadding, @@ -53,7 +54,8 @@ class Dialog extends StatelessWidget { this.shape, this.alignment, this.child, - }) : assert(clipBehavior != null); + }) : assert(clipBehavior != null), + assert(elevation == null || elevation >= 0.0); /// {@template flutter.material.dialog.backgroundColor} /// The background color of the surface of this [Dialog]. @@ -67,12 +69,53 @@ class Dialog extends StatelessWidget { /// {@template flutter.material.dialog.elevation} /// The z-coordinate of this [Dialog]. /// - /// If null then [DialogTheme.elevation] is used, and if that's null then the - /// dialog's elevation is 24.0. + /// Controls how far above the parent the dialog will appear. Elevation is + /// represented by a drop shadow if [shadowColor] is non null, + /// and a surface tint overlay on the background color if [surfaceTintColor] is + /// non null. + /// + /// If null then [DialogTheme.elevation] is used, and if that is null then + /// the elevation will match the Material Design specification for Dialogs. + /// + /// See also: + /// * [Material.elevation], which describes how [elevation] effects the + /// drop shadow or surface tint overlay. + /// * [shadowColor], color of the drop shadow used to indicate the elevation. + /// * [surfaceTintColor], color of an overlay on top of the background + /// color used to indicate the elevation. + /// * , the Material + /// Design specification for dialogs. /// {@endtemplate} - /// {@macro flutter.material.material.elevation} final double? elevation; + /// {@template flutter.material.dialog.shadowColor} + /// The color to paint the [elevation] shadow under the dialog's [Material]. + /// + /// If null then no drop shadow will be painted. + /// + /// See also: + /// * [Material.shadowColor], which describes how the drop shadow is painted. + /// * [elevation], effects how the drop shadow is painted. + /// * [surfaceTintColor], if non-null will also provide a surface tint + /// overlay on the background color to indicate elevation. + /// {@endtemplate} + final Color? shadowColor; + + /// {@template flutter.material.dialog.surfaceTintColor} + /// The color used as a surface tint overlay on the dialog's background color, + /// which reflects the dialog's [elevation]. + /// + /// If null then no surface tint will be applied. + /// + /// See also: + /// * [Material.surfaceTintColor], which describes how the surface tint will + /// be applied to the background color of the dialog. + /// * [elevation], effects the opacity of the surface tint. + /// * [shadowColor], if non-null will also provide a drop shadow to + /// indicate elevation. + /// {@endtemplate} + final Color? surfaceTintColor; + /// {@template flutter.material.dialog.insetAnimationDuration} /// The duration of the animation to show when the system keyboard intrudes /// into the space that the dialog is placed in. @@ -155,6 +198,8 @@ class Dialog extends StatelessWidget { child: Material( color: backgroundColor ?? dialogTheme.backgroundColor ?? Theme.of(context).dialogBackgroundColor, elevation: elevation ?? dialogTheme.elevation ?? defaults.elevation!, + shadowColor: shadowColor ?? dialogTheme.shadowColor ?? defaults.shadowColor, + surfaceTintColor: surfaceTintColor ?? dialogTheme.surfaceTintColor ?? defaults.surfaceTintColor, shape: shape ?? dialogTheme.shape ?? defaults.shape!, type: MaterialType.card, clipBehavior: clipBehavior, @@ -280,6 +325,8 @@ class AlertDialog extends StatelessWidget { this.buttonPadding, this.backgroundColor, this.elevation, + this.shadowColor, + this.surfaceTintColor, this.semanticLabel, this.insetPadding = _defaultInsetPadding, this.clipBehavior = Clip.none, @@ -478,9 +525,14 @@ class AlertDialog extends StatelessWidget { final Color? backgroundColor; /// {@macro flutter.material.dialog.elevation} - /// {@macro flutter.material.material.elevation} final double? elevation; + /// {@macro flutter.material.dialog.shadowColor} + final Color? shadowColor; + + /// {@macro flutter.material.dialog.surfaceTintColor} + final Color? surfaceTintColor; + /// The semantic label of the dialog used by accessibility frameworks to /// announce screen transitions when the dialog is opened and closed. /// @@ -695,6 +747,8 @@ class AlertDialog extends StatelessWidget { return Dialog( backgroundColor: backgroundColor, elevation: elevation, + shadowColor: shadowColor, + surfaceTintColor: surfaceTintColor, insetPadding: insetPadding, clipBehavior: clipBehavior, shape: shape, @@ -860,6 +914,8 @@ class SimpleDialog extends StatelessWidget { this.contentPadding = const EdgeInsets.fromLTRB(0.0, 12.0, 0.0, 16.0), this.backgroundColor, this.elevation, + this.shadowColor, + this.surfaceTintColor, this.semanticLabel, this.insetPadding = _defaultInsetPadding, this.clipBehavior = Clip.none, @@ -915,9 +971,14 @@ class SimpleDialog extends StatelessWidget { final Color? backgroundColor; /// {@macro flutter.material.dialog.elevation} - /// {@macro flutter.material.material.elevation} final double? elevation; + /// {@macro flutter.material.dialog.shadowColor} + final Color? shadowColor; + + /// {@macro flutter.material.dialog.surfaceTintColor} + final Color? surfaceTintColor; + /// The semantic label of the dialog used by accessibility frameworks to /// announce screen transitions when the dialog is opened and closed. /// @@ -1031,6 +1092,8 @@ class SimpleDialog extends StatelessWidget { return Dialog( backgroundColor: backgroundColor, elevation: elevation, + shadowColor: shadowColor, + surfaceTintColor: surfaceTintColor, insetPadding: insetPadding, clipBehavior: clipBehavior, shape: shape, @@ -1296,6 +1359,9 @@ class _DialogDefaultsM2 extends DialogTheme { @override Color? get backgroundColor => Theme.of(context).dialogBackgroundColor; + @override + Color? get shadowColor => Theme.of(context).shadowColor; + @override TextStyle? get titleTextStyle => _textTheme.headline6; @@ -1330,9 +1396,11 @@ class _DialogDefaultsM3 extends DialogTheme { @override Color? get iconColor => _colors.secondary; - // TODO(darrenaustin): overlay should be handled by Material widget: https://github.com/flutter/flutter/issues/9160 @override - Color? get backgroundColor => ElevationOverlay.colorWithOverlay(_colors.surface, _colors.primary, 6.0); + Color? get backgroundColor => _colors.surface; + + @override + Color? get surfaceTintColor => _colors.surfaceTint; @override TextStyle? get titleTextStyle => _textTheme.headlineSmall; diff --git a/packages/flutter/lib/src/material/dialog_theme.dart b/packages/flutter/lib/src/material/dialog_theme.dart index b3c7cd3218d80..a53afee5ca5a7 100644 --- a/packages/flutter/lib/src/material/dialog_theme.dart +++ b/packages/flutter/lib/src/material/dialog_theme.dart @@ -30,6 +30,8 @@ class DialogTheme with Diagnosticable { const DialogTheme({ this.backgroundColor, this.elevation, + this.shadowColor, + this.surfaceTintColor, this.shape, this.alignment, this.iconColor, @@ -44,6 +46,12 @@ class DialogTheme with Diagnosticable { /// Overrides the default value for [Dialog.elevation]. final double? elevation; + /// Overrides the default value for [Dialog.shadowColor]. + final Color? shadowColor; + + /// Overrides the default value for [Dialog.surfaceTintColor]. + final Color? surfaceTintColor; + /// Overrides the default value for [Dialog.shape]. final ShapeBorder? shape; @@ -69,6 +77,8 @@ class DialogTheme with Diagnosticable { DialogTheme copyWith({ Color? backgroundColor, double? elevation, + Color? shadowColor, + Color? surfaceTintColor, ShapeBorder? shape, AlignmentGeometry? alignment, Color? iconColor, @@ -79,6 +89,8 @@ class DialogTheme with Diagnosticable { return DialogTheme( backgroundColor: backgroundColor ?? this.backgroundColor, elevation: elevation ?? this.elevation, + shadowColor: shadowColor ?? this.shadowColor, + surfaceTintColor: surfaceTintColor ?? this.surfaceTintColor, shape: shape ?? this.shape, alignment: alignment ?? this.alignment, iconColor: iconColor ?? this.iconColor, @@ -103,6 +115,8 @@ class DialogTheme with Diagnosticable { return DialogTheme( backgroundColor: Color.lerp(a?.backgroundColor, b?.backgroundColor, t), elevation: lerpDouble(a?.elevation, b?.elevation, t), + shadowColor: Color.lerp(a?.shadowColor, b?.shadowColor, t), + surfaceTintColor: Color.lerp(a?.surfaceTintColor, b?.surfaceTintColor, t), shape: ShapeBorder.lerp(a?.shape, b?.shape, t), alignment: AlignmentGeometry.lerp(a?.alignment, b?.alignment, t), iconColor: Color.lerp(a?.iconColor, b?.iconColor, t), @@ -126,6 +140,8 @@ class DialogTheme with Diagnosticable { return other is DialogTheme && other.backgroundColor == backgroundColor && other.elevation == elevation + && other.shadowColor == shadowColor + && other.surfaceTintColor == surfaceTintColor && other.shape == shape && other.alignment == alignment && other.iconColor == iconColor @@ -139,6 +155,8 @@ class DialogTheme with Diagnosticable { super.debugFillProperties(properties); properties.add(ColorProperty('backgroundColor', backgroundColor)); properties.add(DoubleProperty('elevation', elevation)); + properties.add(ColorProperty('shadowColor', shadowColor)); + properties.add(ColorProperty('surfaceTintColor', surfaceTintColor)); properties.add(DiagnosticsProperty('shape', shape, defaultValue: null)); properties.add(DiagnosticsProperty('alignment', alignment, defaultValue: null)); properties.add(ColorProperty('iconColor', iconColor)); diff --git a/packages/flutter/test/material/dialog_test.dart b/packages/flutter/test/material/dialog_test.dart index f71677cf29ec7..63bf9a2986c34 100644 --- a/packages/flutter/test/material/dialog_test.dart +++ b/packages/flutter/test/material/dialog_test.dart @@ -140,9 +140,13 @@ void main() { testWidgets('Custom dialog elevation', (WidgetTester tester) async { const double customElevation = 12.0; + const Color shadowColor = Color(0xFF000001); + const Color surfaceTintColor = Color(0xFF000002); const AlertDialog dialog = AlertDialog( actions: [ ], elevation: customElevation, + shadowColor: shadowColor, + surfaceTintColor: surfaceTintColor, ); await tester.pumpWidget(_buildAppWithDialog(dialog)); @@ -151,6 +155,8 @@ void main() { final Material materialWidget = _getMaterialFromDialog(tester); expect(materialWidget.elevation, customElevation); + expect(materialWidget.shadowColor, shadowColor); + expect(materialWidget.surfaceTintColor, surfaceTintColor); }); testWidgets('Custom Title Text Style', (WidgetTester tester) async { diff --git a/packages/flutter/test/material/dialog_theme_test.dart b/packages/flutter/test/material/dialog_theme_test.dart index 5666af42daef8..54bdf92937522 100644 --- a/packages/flutter/test/material/dialog_theme_test.dart +++ b/packages/flutter/test/material/dialog_theme_test.dart @@ -51,6 +51,8 @@ void main() { const DialogTheme( backgroundColor: Color(0xff123456), elevation: 8.0, + shadowColor: Color(0xff000001), + surfaceTintColor: Color(0xff000002), alignment: Alignment.bottomLeft, iconColor: Color(0xff654321), titleTextStyle: TextStyle(color: Color(0xffffffff)), @@ -63,6 +65,8 @@ void main() { expect(description, [ 'backgroundColor: Color(0xff123456)', 'elevation: 8.0', + 'shadowColor: Color(0xff000001)', + 'surfaceTintColor: Color(0xff000002)', 'alignment: Alignment.bottomLeft', 'iconColor: Color(0xff654321)', 'titleTextStyle: TextStyle(inherit: true, color: Color(0xffffffff))', @@ -89,11 +93,19 @@ void main() { testWidgets('Custom dialog elevation', (WidgetTester tester) async { const double customElevation = 12.0; + const Color shadowColor = Color(0xFF000001); + const Color surfaceTintColor = Color(0xFF000002); const AlertDialog dialog = AlertDialog( title: Text('Title'), actions: [ ], ); - final ThemeData theme = ThemeData(dialogTheme: const DialogTheme(elevation: customElevation)); + final ThemeData theme = ThemeData( + dialogTheme: const DialogTheme( + elevation: customElevation, + shadowColor: shadowColor, + surfaceTintColor: surfaceTintColor, + ), + ); await tester.pumpWidget( _appWithDialog(tester, dialog, theme: theme), @@ -103,6 +115,8 @@ void main() { final Material materialWidget = _getMaterialFromDialog(tester); expect(materialWidget.elevation, customElevation); + expect(materialWidget.shadowColor, shadowColor); + expect(materialWidget.surfaceTintColor, surfaceTintColor); }); testWidgets('Custom dialog shape', (WidgetTester tester) async {