Fixing elevation issues with Material 3 (#110624)
* Added support for surfaceTintColor and shadowColor to the Dialog widgets. * Updated the defaults for Material.shadowColor and Material.surfaceTint to allow turning off the features with a transparent color. * Added support for shadowColor and surfaceTintColor for Drawer widget.
This commit is contained in:
parent
1b4b480af6
commit
33ed6a3533
@ -31,10 +31,10 @@ class _${blockName}DefaultsM3 extends ChipThemeData {
|
||||
Color? get backgroundColor => ${componentColor("$tokenGroup$variant.container")};
|
||||
|
||||
@override
|
||||
Color? get shadowColor => ${color("$tokenGroup.container.shadow-color")};
|
||||
Color? get shadowColor => ${colorOrTransparent("$tokenGroup.container.shadow-color")};
|
||||
|
||||
@override
|
||||
@override Color? get surfaceTintColor => ${color("$tokenGroup.container.surface-tint-layer.color")};
|
||||
Color? get surfaceTintColor => ${colorOrTransparent("$tokenGroup.container.surface-tint-layer.color")};
|
||||
|
||||
@override
|
||||
Color? get selectedColor => ${componentColor("$tokenGroup$variant.selected.container")};
|
||||
|
@ -34,7 +34,10 @@ class _${blockName}DefaultsM3 extends AppBarTheme {
|
||||
Color? get foregroundColor => ${color('md.comp.top-app-bar.small.headline.color')};
|
||||
|
||||
@override
|
||||
Color? get surfaceTintColor => ${componentColor('md.comp.top-app-bar.small.container.surface-tint-layer')};
|
||||
Color? get shadowColor => ${colorOrTransparent('md.comp.top-app-bar.small.container.shadow-color')};
|
||||
|
||||
@override
|
||||
Color? get surfaceTintColor => ${colorOrTransparent('md.comp.top-app-bar.small.container.surface-tint-layer.color')};
|
||||
|
||||
@override
|
||||
IconThemeData? get iconTheme => IconThemeData(
|
||||
|
@ -24,7 +24,7 @@ class ButtonTemplate extends TokenTemplate {
|
||||
}
|
||||
return '''
|
||||
|
||||
ButtonStyleButton.allOrNull<Color>(Colors.transparent)''';
|
||||
const MaterialStatePropertyAll<Color>(Colors.transparent)''';
|
||||
}
|
||||
|
||||
String _elevation() {
|
||||
@ -49,7 +49,15 @@ class ButtonTemplate extends TokenTemplate {
|
||||
}
|
||||
return '''
|
||||
|
||||
ButtonStyleButton.allOrNull<double>(0.0)''';
|
||||
const MaterialStatePropertyAll<double>(0.0)''';
|
||||
}
|
||||
|
||||
String _elevationColor(String token) {
|
||||
if (tokens.containsKey(token)) {
|
||||
return 'MaterialStatePropertyAll<Color>(${color(token)})';
|
||||
} else {
|
||||
return 'const MaterialStatePropertyAll<Color>(Colors.transparent)';
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
@ -96,34 +104,30 @@ class _${blockName}DefaultsM3 extends ButtonStyle {
|
||||
return null;
|
||||
});
|
||||
|
||||
${tokens.containsKey("$tokenGroup.container.shadow-color") ? '''
|
||||
@override
|
||||
MaterialStateProperty<Color>? get shadowColor =>
|
||||
ButtonStyleButton.allOrNull<Color>(${color("$tokenGroup.container.shadow-color")});''' : '''
|
||||
// No default shadow color'''}
|
||||
${_elevationColor("$tokenGroup.container.shadow-color")};
|
||||
|
||||
${tokens.containsKey("$tokenGroup.container.surface-tint-layer.color") ? '''
|
||||
@override
|
||||
MaterialStateProperty<Color>? get surfaceTintColor =>
|
||||
ButtonStyleButton.allOrNull<Color>(${color("$tokenGroup.container.surface-tint-layer.color")});''' : '''
|
||||
// No default surface tint color'''}
|
||||
${_elevationColor("$tokenGroup.container.surface-tint-layer.color")};
|
||||
|
||||
@override
|
||||
MaterialStateProperty<double>? get elevation =>${_elevation()};
|
||||
|
||||
@override
|
||||
MaterialStateProperty<EdgeInsetsGeometry>? get padding =>
|
||||
ButtonStyleButton.allOrNull<EdgeInsetsGeometry>(_scaledPadding(context));
|
||||
MaterialStatePropertyAll<EdgeInsetsGeometry>(_scaledPadding(context));
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Size>? get minimumSize =>
|
||||
ButtonStyleButton.allOrNull<Size>(const Size(64.0, ${tokens["$tokenGroup.container.height"]}));
|
||||
const MaterialStatePropertyAll<Size>(Size(64.0, ${tokens["$tokenGroup.container.height"]}));
|
||||
|
||||
// No default fixedSize
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Size>? get maximumSize =>
|
||||
ButtonStyleButton.allOrNull<Size>(Size.infinite);
|
||||
const MaterialStatePropertyAll<Size>(Size.infinite);
|
||||
|
||||
${tokens.containsKey("$tokenGroup.outline.color") ? '''
|
||||
@override
|
||||
@ -138,7 +142,7 @@ ${tokens.containsKey("$tokenGroup.outline.color") ? '''
|
||||
|
||||
@override
|
||||
MaterialStateProperty<OutlinedBorder>? get shape =>
|
||||
ButtonStyleButton.allOrNull<OutlinedBorder>(${shape("$tokenGroup.container")});
|
||||
const MaterialStatePropertyAll<OutlinedBorder>(${shape("$tokenGroup.container", '')});
|
||||
|
||||
@override
|
||||
MaterialStateProperty<MouseCursor?>? get mouseCursor =>
|
||||
|
@ -25,10 +25,10 @@ class _${blockName}DefaultsM3 extends CardTheme {
|
||||
Color? get color => ${componentColor("md.comp.elevated-card.container")};
|
||||
|
||||
@override
|
||||
Color? get shadowColor => ${color("md.comp.elevated-card.container.shadow-color")};
|
||||
Color? get shadowColor => ${colorOrTransparent("md.comp.elevated-card.container.shadow-color")};
|
||||
|
||||
@override
|
||||
Color? get surfaceTintColor => ${color("md.comp.elevated-card.container.surface-tint-layer.color")};
|
||||
Color? get surfaceTintColor => ${colorOrTransparent("md.comp.elevated-card.container.surface-tint-layer.color")};
|
||||
}
|
||||
''';
|
||||
}
|
||||
|
@ -27,9 +27,14 @@ 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 shadowColor => ${colorOrTransparent("md.comp.dialog.container.shadow-color")};
|
||||
|
||||
@override
|
||||
Color? get surfaceTintColor => ${colorOrTransparent("md.comp.dialog.container.surface-tint-layer.color")};
|
||||
|
||||
@override
|
||||
TextStyle? get titleTextStyle => ${textStyle("md.comp.dialog.headline")};
|
||||
|
@ -31,10 +31,10 @@ class _${blockName}DefaultsM3 extends ChipThemeData {
|
||||
Color? get backgroundColor => ${componentColor("$tokenGroup$variant.container")};
|
||||
|
||||
@override
|
||||
Color? get shadowColor => ${color("$tokenGroup.container.shadow-color")};
|
||||
Color? get shadowColor => ${colorOrTransparent("$tokenGroup.container.shadow-color")};
|
||||
|
||||
@override
|
||||
@override Color? get surfaceTintColor => ${color("$tokenGroup.container.surface-tint-layer.color")};
|
||||
Color? get surfaceTintColor => ${colorOrTransparent("$tokenGroup.container.surface-tint-layer.color")};
|
||||
|
||||
@override
|
||||
Color? get selectedColor => isEnabled
|
||||
|
@ -9,6 +9,15 @@ class IconButtonTemplate extends TokenTemplate {
|
||||
super.colorSchemePrefix = '_colors.',
|
||||
});
|
||||
|
||||
|
||||
String _elevationColor(String token) {
|
||||
if (tokens.containsKey(token)) {
|
||||
return 'MaterialStatePropertyAll<Color>(${color(token)})';
|
||||
} else {
|
||||
return 'const MaterialStatePropertyAll<Color>(Colors.transparent)';
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
String generate() => '''
|
||||
class _${blockName}DefaultsM3 extends ButtonStyle {
|
||||
@ -26,7 +35,7 @@ class _${blockName}DefaultsM3 extends ButtonStyle {
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Color?>? get backgroundColor =>
|
||||
ButtonStyleButton.allOrNull<Color>(Colors.transparent);
|
||||
const MaterialStatePropertyAll<Color?>(Colors.transparent);
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Color?>? get foregroundColor =>
|
||||
@ -66,37 +75,41 @@ class _${blockName}DefaultsM3 extends ButtonStyle {
|
||||
return null;
|
||||
});
|
||||
|
||||
// No default shadow color
|
||||
|
||||
// No default surface tint color
|
||||
|
||||
@override
|
||||
MaterialStateProperty<double>? get elevation =>
|
||||
ButtonStyleButton.allOrNull<double>(0.0);
|
||||
const MaterialStatePropertyAll<double>(0.0);
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Color>? get shadowColor =>
|
||||
${_elevationColor("md.comp.icon-button.container.shadow-color")};
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Color>? get surfaceTintColor =>
|
||||
${_elevationColor("md.comp.icon-button.container.surface-tint-layer.color")};
|
||||
|
||||
@override
|
||||
MaterialStateProperty<EdgeInsetsGeometry>? get padding =>
|
||||
ButtonStyleButton.allOrNull<EdgeInsetsGeometry>(const EdgeInsets.all(8.0));
|
||||
const MaterialStatePropertyAll<EdgeInsetsGeometry>(EdgeInsets.all(8.0));
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Size>? get minimumSize =>
|
||||
ButtonStyleButton.allOrNull<Size>(const Size(${tokens["md.comp.icon-button.state-layer.size"]}, ${tokens["md.comp.icon-button.state-layer.size"]}));
|
||||
const MaterialStatePropertyAll<Size>(Size(${tokens["md.comp.icon-button.state-layer.size"]}, ${tokens["md.comp.icon-button.state-layer.size"]}));
|
||||
|
||||
// No default fixedSize
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Size>? get maximumSize =>
|
||||
ButtonStyleButton.allOrNull<Size>(Size.infinite);
|
||||
const MaterialStatePropertyAll<Size>(Size.infinite);
|
||||
|
||||
@override
|
||||
MaterialStateProperty<double>? get iconSize =>
|
||||
ButtonStyleButton.allOrNull<double>(${tokens["md.comp.icon-button.icon.size"]});
|
||||
const MaterialStatePropertyAll<double>(${tokens["md.comp.icon-button.icon.size"]});
|
||||
|
||||
// No default side
|
||||
|
||||
@override
|
||||
MaterialStateProperty<OutlinedBorder>? get shape =>
|
||||
ButtonStyleButton.allOrNull<OutlinedBorder>(${shape("md.comp.icon-button.state-layer")});
|
||||
const MaterialStatePropertyAll<OutlinedBorder>(${shape("md.comp.icon-button.state-layer", "")});
|
||||
|
||||
@override
|
||||
MaterialStateProperty<MouseCursor?>? get mouseCursor =>
|
||||
|
@ -30,10 +30,10 @@ class _${blockName}DefaultsM3 extends ChipThemeData {
|
||||
Color? get backgroundColor => ${componentColor("$tokenGroup$variant.container")};
|
||||
|
||||
@override
|
||||
Color? get shadowColor => ${color("$tokenGroup.container.shadow-color")};
|
||||
Color? get shadowColor => ${colorOrTransparent("$tokenGroup.container.shadow-color")};
|
||||
|
||||
@override
|
||||
@override Color? get surfaceTintColor => ${color("$tokenGroup.container.surface-tint-layer.color")};
|
||||
Color? get surfaceTintColor => ${colorOrTransparent("$tokenGroup.container.surface-tint-layer.color")};
|
||||
|
||||
@override
|
||||
Color? get selectedColor => ${componentColor("$tokenGroup$variant.selected.container")};
|
||||
|
@ -26,7 +26,9 @@ class _${blockName}DefaultsM3 extends NavigationBarThemeData {
|
||||
|
||||
@override Color? get backgroundColor => ${componentColor("md.comp.navigation-bar.container")};
|
||||
|
||||
@override Color? get surfaceTintColor => ${color("md.comp.navigation-bar.container.surface-tint-layer.color")};
|
||||
@override Color? get shadowColor => ${colorOrTransparent("md.comp.navigation-bar.container.shadow-color")};
|
||||
|
||||
@override Color? get surfaceTintColor => ${colorOrTransparent("md.comp.navigation-bar.container.surface-tint-layer.color")};
|
||||
|
||||
@override MaterialStateProperty<IconThemeData?>? get iconTheme {
|
||||
return MaterialStateProperty.resolveWith((Set<MaterialState> states) {
|
||||
|
@ -97,16 +97,28 @@ abstract class TokenTemplate {
|
||||
/// If there is a value for the given token, this will return
|
||||
/// the value prepended with [colorSchemePrefix].
|
||||
///
|
||||
/// Otherwise it will return 'null'.
|
||||
/// Otherwise it will return [defaultValue].
|
||||
///
|
||||
/// See also:
|
||||
/// * [componentColor], that provides support for an optional opacity.
|
||||
String color(String colorToken) {
|
||||
String color(String colorToken, [String defaultValue = 'null']) {
|
||||
return tokens.containsKey(colorToken)
|
||||
? '$colorSchemePrefix${tokens[colorToken]}'
|
||||
: 'null';
|
||||
: defaultValue;
|
||||
}
|
||||
|
||||
/// Generate a [ColorScheme] color name for the given token or a transparent
|
||||
/// color if there is no value for the token.
|
||||
///
|
||||
/// If there is a value for the given token, this will return
|
||||
/// the value prepended with [colorSchemePrefix].
|
||||
///
|
||||
/// Otherwise it will return 'Colors.transparent'.
|
||||
///
|
||||
/// See also:
|
||||
/// * [componentColor], that provides support for an optional opacity.
|
||||
String? colorOrTransparent(String token) => color(token, 'Colors.transparent');
|
||||
|
||||
/// Generate a [ColorScheme] color name for the given component's color
|
||||
/// with opacity if available.
|
||||
///
|
||||
@ -154,18 +166,18 @@ abstract class TokenTemplate {
|
||||
/// Currently supports family:
|
||||
/// - "SHAPE_FAMILY_ROUNDED_CORNERS" which maps to [RoundedRectangleBorder].
|
||||
/// - "SHAPE_FAMILY_CIRCULAR" which maps to a [StadiumBorder].
|
||||
String shape(String componentToken) {
|
||||
String shape(String componentToken, [String prefix = 'const ']) {
|
||||
final Map<String, dynamic> shape = tokens[tokens['$componentToken.shape']!]! as Map<String, dynamic>;
|
||||
switch (shape['family']) {
|
||||
case 'SHAPE_FAMILY_ROUNDED_CORNERS':
|
||||
return 'const RoundedRectangleBorder(borderRadius: '
|
||||
return '${prefix}RoundedRectangleBorder(borderRadius: '
|
||||
'BorderRadius.only('
|
||||
'topLeft: Radius.circular(${shape['topLeft']}), '
|
||||
'topRight: Radius.circular(${shape['topRight']}), '
|
||||
'bottomLeft: Radius.circular(${shape['bottomLeft']}), '
|
||||
'bottomRight: Radius.circular(${shape['bottomRight']})))';
|
||||
case 'SHAPE_FAMILY_CIRCULAR':
|
||||
return 'const StadiumBorder()';
|
||||
return '${prefix}StadiumBorder()';
|
||||
}
|
||||
print('Unsupported shape family type: ${shape['family']} for $componentToken');
|
||||
return '';
|
||||
|
@ -16,7 +16,7 @@ void main() {
|
||||
|
||||
expect(find.widgetWithText(AppBar, 'AppBar Demo'), findsOneWidget);
|
||||
Material appbarMaterial = _getAppBarMaterial(tester);
|
||||
expect(appbarMaterial.shadowColor, null);
|
||||
expect(appbarMaterial.shadowColor, Colors.transparent);
|
||||
expect(appbarMaterial.elevation, 0);
|
||||
|
||||
await tester.drag(find.text('Item 4'), _kOffset, touchSlopY: 0, warnIfMissed: false);
|
||||
|
@ -7,6 +7,7 @@ import 'package:flutter/widgets.dart';
|
||||
|
||||
import 'chip.dart';
|
||||
import 'chip_theme.dart';
|
||||
import 'colors.dart';
|
||||
import 'debug.dart';
|
||||
import 'theme.dart';
|
||||
import 'theme_data.dart';
|
||||
@ -196,10 +197,10 @@ class _ActionChipDefaultsM3 extends ChipThemeData {
|
||||
Color? get backgroundColor => null;
|
||||
|
||||
@override
|
||||
Color? get shadowColor => null;
|
||||
Color? get shadowColor => Colors.transparent;
|
||||
|
||||
@override
|
||||
@override Color? get surfaceTintColor => Theme.of(context).colorScheme.surfaceTint;
|
||||
Color? get surfaceTintColor => Theme.of(context).colorScheme.surfaceTint;
|
||||
|
||||
@override
|
||||
Color? get selectedColor => null;
|
||||
|
@ -12,6 +12,7 @@ import 'package:flutter/widgets.dart';
|
||||
import 'app_bar_theme.dart';
|
||||
import 'back_button.dart';
|
||||
import 'color_scheme.dart';
|
||||
import 'colors.dart';
|
||||
import 'constants.dart';
|
||||
import 'debug.dart';
|
||||
import 'flexible_space_bar.dart';
|
||||
@ -2370,6 +2371,9 @@ class _AppBarDefaultsM3 extends AppBarTheme {
|
||||
@override
|
||||
Color? get foregroundColor => _colors.onSurface;
|
||||
|
||||
@override
|
||||
Color? get shadowColor => Colors.transparent;
|
||||
|
||||
@override
|
||||
Color? get surfaceTintColor => _colors.surfaceTint;
|
||||
|
||||
|
@ -213,7 +213,7 @@ class _FilterChipDefaultsM3 extends ChipThemeData {
|
||||
Color? get shadowColor => Theme.of(context).colorScheme.shadow;
|
||||
|
||||
@override
|
||||
@override Color? get surfaceTintColor => Theme.of(context).colorScheme.surfaceTint;
|
||||
Color? get surfaceTintColor => Theme.of(context).colorScheme.surfaceTint;
|
||||
|
||||
@override
|
||||
Color? get selectedColor => isEnabled
|
||||
|
@ -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,63 @@ 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.
|
||||
/// * <https://m3.material.io/components/dialogs/overview>, the Material
|
||||
/// Design specification for dialogs.
|
||||
/// {@endtemplate}
|
||||
/// {@macro flutter.material.material.elevation}
|
||||
final double? elevation;
|
||||
|
||||
/// {@template flutter.material.dialog.shadowColor}
|
||||
/// The color used to paint a drop shadow under the dialog's [Material],
|
||||
/// which reflects the dialog's [elevation].
|
||||
///
|
||||
/// If null and [ThemeData.useMaterial3] is true then no drop shadow will
|
||||
/// be rendered.
|
||||
///
|
||||
/// If null and [ThemeData.useMaterial3] is false then it will default to
|
||||
/// [ThemeData.shadowColor].
|
||||
///
|
||||
/// See also:
|
||||
/// * [Material.shadowColor], which describes how the drop shadow is painted.
|
||||
/// * [elevation], which affects how the drop shadow is painted.
|
||||
/// * [surfaceTintColor], which can be used to indicate elevation through
|
||||
/// tinting the background color.
|
||||
/// {@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 [ThemeData.useMaterial3] is false property has no effect.
|
||||
///
|
||||
/// If null and [ThemeData.useMaterial3] is true then [ThemeData]'s
|
||||
/// [ColorScheme.surfaceTint] will be used.
|
||||
///
|
||||
/// To disable this feature, set [surfaceTintColor] to [Colors.transparent].
|
||||
///
|
||||
/// See also:
|
||||
/// * [Material.surfaceTintColor], which describes how the surface tint will
|
||||
/// be applied to the background color of the dialog.
|
||||
/// * [elevation], which affects the opacity of the surface tint.
|
||||
/// * [shadowColor], which can be used to indicate elevation through
|
||||
/// a drop shadow.
|
||||
/// {@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 +208,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 +335,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 +535,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 +757,8 @@ class AlertDialog extends StatelessWidget {
|
||||
return Dialog(
|
||||
backgroundColor: backgroundColor,
|
||||
elevation: elevation,
|
||||
shadowColor: shadowColor,
|
||||
surfaceTintColor: surfaceTintColor,
|
||||
insetPadding: insetPadding,
|
||||
clipBehavior: clipBehavior,
|
||||
shape: shape,
|
||||
@ -860,6 +924,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 +981,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 +1102,8 @@ class SimpleDialog extends StatelessWidget {
|
||||
return Dialog(
|
||||
backgroundColor: backgroundColor,
|
||||
elevation: elevation,
|
||||
shadowColor: shadowColor,
|
||||
surfaceTintColor: surfaceTintColor,
|
||||
insetPadding: insetPadding,
|
||||
clipBehavior: clipBehavior,
|
||||
shape: shape,
|
||||
@ -1296,6 +1369,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.titleLarge;
|
||||
|
||||
@ -1330,9 +1406,14 @@ 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 shadowColor => Colors.transparent;
|
||||
|
||||
@override
|
||||
Color? get surfaceTintColor => _colors.surfaceTint;
|
||||
|
||||
@override
|
||||
TextStyle? get titleTextStyle => _textTheme.headlineSmall;
|
||||
|
@ -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<ShapeBorder>('shape', shape, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<AlignmentGeometry>('alignment', alignment, defaultValue: null));
|
||||
properties.add(ColorProperty('iconColor', iconColor));
|
||||
|
@ -147,6 +147,8 @@ class Drawer extends StatelessWidget {
|
||||
super.key,
|
||||
this.backgroundColor,
|
||||
this.elevation,
|
||||
this.shadowColor,
|
||||
this.surfaceTintColor,
|
||||
this.shape,
|
||||
this.width,
|
||||
this.child,
|
||||
@ -168,6 +170,40 @@ class Drawer extends StatelessWidget {
|
||||
/// is also null, then it defaults to 16.0.
|
||||
final double? elevation;
|
||||
|
||||
/// The color used to paint a drop shadow under the drawer's [Material],
|
||||
/// which reflects the drawer's [elevation].
|
||||
///
|
||||
/// If null and [ThemeData.useMaterial3] is true then no drop shadow will
|
||||
/// be rendered.
|
||||
///
|
||||
/// If null and [ThemeData.useMaterial3] is false then it will default to
|
||||
/// [ThemeData.shadowColor].
|
||||
///
|
||||
/// See also:
|
||||
/// * [Material.shadowColor], which describes how the drop shadow is painted.
|
||||
/// * [elevation], which affects how the drop shadow is painted.
|
||||
/// * [surfaceTintColor], which can be used to indicate elevation through
|
||||
/// tinting the background color.
|
||||
final Color? shadowColor;
|
||||
|
||||
/// The color used as a surface tint overlay on the drawer's background color,
|
||||
/// which reflects the drawer's [elevation].
|
||||
///
|
||||
/// If [ThemeData.useMaterial3] is false property has no effect.
|
||||
///
|
||||
/// If null and [ThemeData.useMaterial3] is true then [ThemeData]'s
|
||||
/// [ColorScheme.surfaceTint] will be used.
|
||||
///
|
||||
/// To disable this feature, set [surfaceTintColor] to [Colors.transparent].
|
||||
///
|
||||
/// See also:
|
||||
/// * [Material.surfaceTintColor], which describes how the surface tint will
|
||||
/// be applied to the background color of the drawer.
|
||||
/// * [elevation], which affects the opacity of the surface tint.
|
||||
/// * [shadowColor], which can be used to indicate elevation through
|
||||
/// a drop shadow.
|
||||
final Color? surfaceTintColor;
|
||||
|
||||
/// The shape of the drawer.
|
||||
///
|
||||
/// Defines the drawer's [Material.shape].
|
||||
@ -189,7 +225,7 @@ class Drawer extends StatelessWidget {
|
||||
/// {@macro flutter.widgets.ProxyWidget.child}
|
||||
final Widget? child;
|
||||
|
||||
/// The semantic label of the dialog used by accessibility frameworks to
|
||||
/// The semantic label of the drawer used by accessibility frameworks to
|
||||
/// announce screen transitions when the drawer is opened and closed.
|
||||
///
|
||||
/// If this label is not provided, it will default to
|
||||
@ -216,6 +252,7 @@ class Drawer extends StatelessWidget {
|
||||
case TargetPlatform.windows:
|
||||
label = semanticLabel ?? MaterialLocalizations.of(context).drawerLabel;
|
||||
}
|
||||
final bool useMaterial3 = Theme.of(context).useMaterial3;
|
||||
return Semantics(
|
||||
scopesRoute: true,
|
||||
namesRoute: true,
|
||||
@ -226,6 +263,8 @@ class Drawer extends StatelessWidget {
|
||||
child: Material(
|
||||
color: backgroundColor ?? drawerTheme.backgroundColor,
|
||||
elevation: elevation ?? drawerTheme.elevation ?? 16.0,
|
||||
shadowColor: shadowColor ?? drawerTheme.shadowColor ?? (useMaterial3 ? Colors.transparent : Theme.of(context).shadowColor),
|
||||
surfaceTintColor: surfaceTintColor ?? drawerTheme.surfaceTintColor ?? (useMaterial3 ? Theme.of(context).colorScheme.surfaceTint : null),
|
||||
shape: shape ?? drawerTheme.shape,
|
||||
child: child,
|
||||
),
|
||||
|
@ -38,6 +38,8 @@ class DrawerThemeData with Diagnosticable {
|
||||
this.backgroundColor,
|
||||
this.scrimColor,
|
||||
this.elevation,
|
||||
this.shadowColor,
|
||||
this.surfaceTintColor,
|
||||
this.shape,
|
||||
this.width,
|
||||
});
|
||||
@ -51,6 +53,12 @@ class DrawerThemeData with Diagnosticable {
|
||||
/// Overrides the default value of [Drawer.elevation].
|
||||
final double? elevation;
|
||||
|
||||
/// Overrides the default value for [Drawer.shadowColor].
|
||||
final Color? shadowColor;
|
||||
|
||||
/// Overrides the default value for [Drawer.surfaceTintColor].
|
||||
final Color? surfaceTintColor;
|
||||
|
||||
/// Overrides the default value of [Drawer.shape].
|
||||
final ShapeBorder? shape;
|
||||
|
||||
@ -63,6 +71,8 @@ class DrawerThemeData with Diagnosticable {
|
||||
Color? backgroundColor,
|
||||
Color? scrimColor,
|
||||
double? elevation,
|
||||
Color? shadowColor,
|
||||
Color? surfaceTintColor,
|
||||
ShapeBorder? shape,
|
||||
double? width,
|
||||
}) {
|
||||
@ -70,6 +80,8 @@ class DrawerThemeData with Diagnosticable {
|
||||
backgroundColor: backgroundColor ?? this.backgroundColor,
|
||||
scrimColor: scrimColor ?? this.scrimColor,
|
||||
elevation: elevation ?? this.elevation,
|
||||
shadowColor: shadowColor ?? this.shadowColor,
|
||||
surfaceTintColor: surfaceTintColor ?? this.surfaceTintColor,
|
||||
shape: shape ?? this.shape,
|
||||
width: width ?? this.width,
|
||||
);
|
||||
@ -89,6 +101,8 @@ class DrawerThemeData with Diagnosticable {
|
||||
backgroundColor: Color.lerp(a?.backgroundColor, b?.backgroundColor, t),
|
||||
scrimColor: Color.lerp(a?.scrimColor, b?.scrimColor, 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),
|
||||
width: lerpDouble(a?.width, b?.width, t),
|
||||
);
|
||||
@ -99,6 +113,8 @@ class DrawerThemeData with Diagnosticable {
|
||||
backgroundColor,
|
||||
scrimColor,
|
||||
elevation,
|
||||
shadowColor,
|
||||
surfaceTintColor,
|
||||
shape,
|
||||
width,
|
||||
);
|
||||
@ -115,6 +131,8 @@ class DrawerThemeData with Diagnosticable {
|
||||
&& other.backgroundColor == backgroundColor
|
||||
&& other.scrimColor == scrimColor
|
||||
&& other.elevation == elevation
|
||||
&& other.shadowColor == shadowColor
|
||||
&& other.surfaceTintColor == surfaceTintColor
|
||||
&& other.shape == shape
|
||||
&& other.width == width;
|
||||
}
|
||||
@ -125,6 +143,8 @@ class DrawerThemeData with Diagnosticable {
|
||||
properties.add(ColorProperty('backgroundColor', backgroundColor, defaultValue: null));
|
||||
properties.add(ColorProperty('scrimColor', scrimColor, defaultValue: null));
|
||||
properties.add(DoubleProperty('elevation', elevation, defaultValue: null));
|
||||
properties.add(ColorProperty('shadowColor', shadowColor, defaultValue: null));
|
||||
properties.add(ColorProperty('surfaceTintColor', surfaceTintColor, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<ShapeBorder>('shape', shape, defaultValue: null));
|
||||
properties.add(DoubleProperty('width', width, defaultValue: null));
|
||||
}
|
||||
|
@ -582,11 +582,11 @@ class _ElevatedButtonDefaultsM3 extends ButtonStyle {
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Color>? get shadowColor =>
|
||||
ButtonStyleButton.allOrNull<Color>(_colors.shadow);
|
||||
MaterialStatePropertyAll<Color>(_colors.shadow);
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Color>? get surfaceTintColor =>
|
||||
ButtonStyleButton.allOrNull<Color>(_colors.surfaceTint);
|
||||
MaterialStatePropertyAll<Color>(_colors.surfaceTint);
|
||||
|
||||
@override
|
||||
MaterialStateProperty<double>? get elevation =>
|
||||
@ -608,23 +608,23 @@ class _ElevatedButtonDefaultsM3 extends ButtonStyle {
|
||||
|
||||
@override
|
||||
MaterialStateProperty<EdgeInsetsGeometry>? get padding =>
|
||||
ButtonStyleButton.allOrNull<EdgeInsetsGeometry>(_scaledPadding(context));
|
||||
MaterialStatePropertyAll<EdgeInsetsGeometry>(_scaledPadding(context));
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Size>? get minimumSize =>
|
||||
ButtonStyleButton.allOrNull<Size>(const Size(64.0, 40.0));
|
||||
const MaterialStatePropertyAll<Size>(Size(64.0, 40.0));
|
||||
|
||||
// No default fixedSize
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Size>? get maximumSize =>
|
||||
ButtonStyleButton.allOrNull<Size>(Size.infinite);
|
||||
const MaterialStatePropertyAll<Size>(Size.infinite);
|
||||
|
||||
// No default side
|
||||
|
||||
@override
|
||||
MaterialStateProperty<OutlinedBorder>? get shape =>
|
||||
ButtonStyleButton.allOrNull<OutlinedBorder>(const StadiumBorder());
|
||||
const MaterialStatePropertyAll<OutlinedBorder>(StadiumBorder());
|
||||
|
||||
@override
|
||||
MaterialStateProperty<MouseCursor?>? get mouseCursor =>
|
||||
|
@ -6,6 +6,7 @@ import 'dart:math' as math;
|
||||
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
import 'colors.dart';
|
||||
import 'theme.dart';
|
||||
|
||||
/// A utility class for dealing with the overlay color needed
|
||||
@ -23,11 +24,12 @@ class ElevationOverlay {
|
||||
/// elevated. The amount of opacity will vary with the elevation as described
|
||||
/// in: https://m3.material.io/styles/color/the-color-system/color-roles.
|
||||
///
|
||||
/// If [surfaceTint] is not null then the returned color will be the given
|
||||
/// [color] with the [surfaceTint] of the appropriate opacity applies to it.
|
||||
/// Otherwise it will just return [color] unmodified.
|
||||
/// If [surfaceTint] is not null and not completely transparent ([Color.alpha]
|
||||
/// is 0), then the returned color will be the given [color] with the
|
||||
/// [surfaceTint] of the appropriate opacity applied to it. Otherwise it will
|
||||
/// just return [color] unmodified.
|
||||
static Color applySurfaceTint(Color color, Color? surfaceTint, double elevation) {
|
||||
if (surfaceTint != null) {
|
||||
if (surfaceTint != null && surfaceTint != Colors.transparent) {
|
||||
return Color.alphaBlend(surfaceTint.withOpacity(_surfaceTintOpacityForElevation(elevation)), color);
|
||||
}
|
||||
return color;
|
||||
|
@ -11,6 +11,7 @@ import 'package:flutter/widgets.dart';
|
||||
import 'button_style.dart';
|
||||
import 'button_style_button.dart';
|
||||
import 'color_scheme.dart';
|
||||
import 'colors.dart';
|
||||
import 'constants.dart';
|
||||
import 'filled_button_theme.dart';
|
||||
import 'ink_well.dart';
|
||||
@ -551,9 +552,11 @@ class _FilledButtonDefaultsM3 extends ButtonStyle {
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Color>? get shadowColor =>
|
||||
ButtonStyleButton.allOrNull<Color>(_colors.shadow);
|
||||
MaterialStatePropertyAll<Color>(_colors.shadow);
|
||||
|
||||
// No default surface tint color
|
||||
@override
|
||||
MaterialStateProperty<Color>? get surfaceTintColor =>
|
||||
const MaterialStatePropertyAll<Color>(Colors.transparent);
|
||||
|
||||
@override
|
||||
MaterialStateProperty<double>? get elevation =>
|
||||
@ -575,23 +578,23 @@ class _FilledButtonDefaultsM3 extends ButtonStyle {
|
||||
|
||||
@override
|
||||
MaterialStateProperty<EdgeInsetsGeometry>? get padding =>
|
||||
ButtonStyleButton.allOrNull<EdgeInsetsGeometry>(_scaledPadding(context));
|
||||
MaterialStatePropertyAll<EdgeInsetsGeometry>(_scaledPadding(context));
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Size>? get minimumSize =>
|
||||
ButtonStyleButton.allOrNull<Size>(const Size(64.0, 40.0));
|
||||
const MaterialStatePropertyAll<Size>(Size(64.0, 40.0));
|
||||
|
||||
// No default fixedSize
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Size>? get maximumSize =>
|
||||
ButtonStyleButton.allOrNull<Size>(Size.infinite);
|
||||
const MaterialStatePropertyAll<Size>(Size.infinite);
|
||||
|
||||
// No default side
|
||||
|
||||
@override
|
||||
MaterialStateProperty<OutlinedBorder>? get shape =>
|
||||
ButtonStyleButton.allOrNull<OutlinedBorder>(const StadiumBorder());
|
||||
const MaterialStatePropertyAll<OutlinedBorder>(StadiumBorder());
|
||||
|
||||
@override
|
||||
MaterialStateProperty<MouseCursor?>? get mouseCursor =>
|
||||
@ -673,9 +676,11 @@ class _FilledTonalButtonDefaultsM3 extends ButtonStyle {
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Color>? get shadowColor =>
|
||||
ButtonStyleButton.allOrNull<Color>(_colors.shadow);
|
||||
MaterialStatePropertyAll<Color>(_colors.shadow);
|
||||
|
||||
// No default surface tint color
|
||||
@override
|
||||
MaterialStateProperty<Color>? get surfaceTintColor =>
|
||||
const MaterialStatePropertyAll<Color>(Colors.transparent);
|
||||
|
||||
@override
|
||||
MaterialStateProperty<double>? get elevation =>
|
||||
@ -697,23 +702,23 @@ class _FilledTonalButtonDefaultsM3 extends ButtonStyle {
|
||||
|
||||
@override
|
||||
MaterialStateProperty<EdgeInsetsGeometry>? get padding =>
|
||||
ButtonStyleButton.allOrNull<EdgeInsetsGeometry>(_scaledPadding(context));
|
||||
MaterialStatePropertyAll<EdgeInsetsGeometry>(_scaledPadding(context));
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Size>? get minimumSize =>
|
||||
ButtonStyleButton.allOrNull<Size>(const Size(64.0, 40.0));
|
||||
const MaterialStatePropertyAll<Size>(Size(64.0, 40.0));
|
||||
|
||||
// No default fixedSize
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Size>? get maximumSize =>
|
||||
ButtonStyleButton.allOrNull<Size>(Size.infinite);
|
||||
const MaterialStatePropertyAll<Size>(Size.infinite);
|
||||
|
||||
// No default side
|
||||
|
||||
@override
|
||||
MaterialStateProperty<OutlinedBorder>? get shape =>
|
||||
ButtonStyleButton.allOrNull<OutlinedBorder>(const StadiumBorder());
|
||||
const MaterialStatePropertyAll<OutlinedBorder>(StadiumBorder());
|
||||
|
||||
@override
|
||||
MaterialStateProperty<MouseCursor?>? get mouseCursor =>
|
||||
|
@ -222,7 +222,7 @@ class _FilterChipDefaultsM3 extends ChipThemeData {
|
||||
Color? get shadowColor => Theme.of(context).colorScheme.shadow;
|
||||
|
||||
@override
|
||||
@override Color? get surfaceTintColor => Theme.of(context).colorScheme.surfaceTint;
|
||||
Color? get surfaceTintColor => Theme.of(context).colorScheme.surfaceTint;
|
||||
|
||||
@override
|
||||
Color? get selectedColor => isEnabled
|
||||
|
@ -979,7 +979,7 @@ class _IconButtonDefaultsM3 extends ButtonStyle {
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Color?>? get backgroundColor =>
|
||||
ButtonStyleButton.allOrNull<Color>(Colors.transparent);
|
||||
const MaterialStatePropertyAll<Color?>(Colors.transparent);
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Color?>? get foregroundColor =>
|
||||
@ -1019,37 +1019,41 @@ class _IconButtonDefaultsM3 extends ButtonStyle {
|
||||
return null;
|
||||
});
|
||||
|
||||
// No default shadow color
|
||||
|
||||
// No default surface tint color
|
||||
|
||||
@override
|
||||
MaterialStateProperty<double>? get elevation =>
|
||||
ButtonStyleButton.allOrNull<double>(0.0);
|
||||
const MaterialStatePropertyAll<double>(0.0);
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Color>? get shadowColor =>
|
||||
const MaterialStatePropertyAll<Color>(Colors.transparent);
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Color>? get surfaceTintColor =>
|
||||
const MaterialStatePropertyAll<Color>(Colors.transparent);
|
||||
|
||||
@override
|
||||
MaterialStateProperty<EdgeInsetsGeometry>? get padding =>
|
||||
ButtonStyleButton.allOrNull<EdgeInsetsGeometry>(const EdgeInsets.all(8.0));
|
||||
const MaterialStatePropertyAll<EdgeInsetsGeometry>(EdgeInsets.all(8.0));
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Size>? get minimumSize =>
|
||||
ButtonStyleButton.allOrNull<Size>(const Size(40.0, 40.0));
|
||||
const MaterialStatePropertyAll<Size>(Size(40.0, 40.0));
|
||||
|
||||
// No default fixedSize
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Size>? get maximumSize =>
|
||||
ButtonStyleButton.allOrNull<Size>(Size.infinite);
|
||||
const MaterialStatePropertyAll<Size>(Size.infinite);
|
||||
|
||||
@override
|
||||
MaterialStateProperty<double>? get iconSize =>
|
||||
ButtonStyleButton.allOrNull<double>(24.0);
|
||||
const MaterialStatePropertyAll<double>(24.0);
|
||||
|
||||
// No default side
|
||||
|
||||
@override
|
||||
MaterialStateProperty<OutlinedBorder>? get shape =>
|
||||
ButtonStyleButton.allOrNull<OutlinedBorder>(const StadiumBorder());
|
||||
const MaterialStatePropertyAll<OutlinedBorder>(StadiumBorder());
|
||||
|
||||
@override
|
||||
MaterialStateProperty<MouseCursor?>? get mouseCursor =>
|
||||
|
@ -7,6 +7,7 @@ import 'package:flutter/widgets.dart';
|
||||
|
||||
import 'chip.dart';
|
||||
import 'chip_theme.dart';
|
||||
import 'colors.dart';
|
||||
import 'debug.dart';
|
||||
import 'icons.dart';
|
||||
import 'theme.dart';
|
||||
@ -268,10 +269,10 @@ class _InputChipDefaultsM3 extends ChipThemeData {
|
||||
Color? get backgroundColor => null;
|
||||
|
||||
@override
|
||||
Color? get shadowColor => null;
|
||||
Color? get shadowColor => Colors.transparent;
|
||||
|
||||
@override
|
||||
@override Color? get surfaceTintColor => null;
|
||||
Color? get surfaceTintColor => Colors.transparent;
|
||||
|
||||
@override
|
||||
Color? get selectedColor => Theme.of(context).colorScheme.secondaryContainer;
|
||||
|
@ -258,12 +258,12 @@ class Material extends StatefulWidget {
|
||||
|
||||
/// The color to paint the shadow below the material.
|
||||
///
|
||||
/// When [ThemeData.useMaterial3] is true, and this is null, then no drop
|
||||
/// shadow will be rendered for this material. If it is non-null, then this
|
||||
/// color will be used to render a drop shadow below the material.
|
||||
/// If null and [ThemeData.useMaterial3] is true then [ThemeData]'s
|
||||
/// [ColorScheme.shadow] will be used. If [ThemeData.useMaterial3] is false
|
||||
/// then [ThemeData.shadowColor] will be used.
|
||||
///
|
||||
/// When [ThemeData.useMaterial3] is false, and this is null, then
|
||||
/// [ThemeData.shadowColor] is used, which defaults to fully opaque black.
|
||||
/// To remove the drop shadow when [elevation] is greater than 0, set
|
||||
/// [shadowColor] to [Colors.transparent].
|
||||
///
|
||||
/// See also:
|
||||
/// * [ThemeData.useMaterial3], which determines the default value for this
|
||||
@ -282,9 +282,9 @@ class Material extends StatefulWidget {
|
||||
///
|
||||
/// If [ThemeData.useMaterial3] is false, then this property is not used.
|
||||
///
|
||||
/// If [ThemeData.useMaterial3] is true and [surfaceTintColor] is not null,
|
||||
/// then it will be used to overlay the base [color] with an opacity based
|
||||
/// on the [elevation].
|
||||
/// If [ThemeData.useMaterial3] is true and [surfaceTintColor] is not null and
|
||||
/// not [Colors.transparent], then it will be used to overlay the base [color]
|
||||
/// with an opacity based on the [elevation].
|
||||
///
|
||||
/// Otherwise, no surface tint will be applied.
|
||||
///
|
||||
@ -404,7 +404,7 @@ class _MaterialState extends State<Material> with TickerProviderStateMixin {
|
||||
Widget build(BuildContext context) {
|
||||
final ThemeData theme = Theme.of(context);
|
||||
final Color? backgroundColor = _getBackgroundColor(context);
|
||||
final Color? modelShadowColor = widget.shadowColor ?? (theme.useMaterial3 ? null : theme.shadowColor);
|
||||
final Color modelShadowColor = widget.shadowColor ?? (theme.useMaterial3 ? theme.colorScheme.shadow : theme.shadowColor);
|
||||
// If no shadow color is specified, use 0 for elevation in the model so a drop shadow won't be painted.
|
||||
final double modelElevation = modelShadowColor != null ? widget.elevation : 0;
|
||||
assert(
|
||||
@ -458,7 +458,7 @@ class _MaterialState extends State<Material> with TickerProviderStateMixin {
|
||||
clipBehavior: widget.clipBehavior,
|
||||
elevation: modelElevation,
|
||||
color: color,
|
||||
shadowColor: modelShadowColor ?? const Color(0x00000000),
|
||||
shadowColor: modelShadowColor,
|
||||
animateColor: false,
|
||||
child: contents,
|
||||
);
|
||||
|
@ -67,8 +67,9 @@ class NavigationBar extends StatelessWidget {
|
||||
required this.destinations,
|
||||
this.onDestinationSelected,
|
||||
this.backgroundColor,
|
||||
this.surfaceTintColor,
|
||||
this.elevation,
|
||||
this.shadowColor,
|
||||
this.surfaceTintColor,
|
||||
this.height,
|
||||
this.labelBehavior,
|
||||
}) : assert(destinations != null && destinations.length >= 2),
|
||||
@ -109,6 +110,22 @@ class NavigationBar extends StatelessWidget {
|
||||
/// and [ColorScheme.onSurface] using an [ElevationOverlay].
|
||||
final Color? backgroundColor;
|
||||
|
||||
/// The elevation of the [NavigationBar] itself.
|
||||
///
|
||||
/// If null, [NavigationBarThemeData.elevation] is used. If that
|
||||
/// is also null, then if [ThemeData.useMaterial3] is true then it will
|
||||
/// be 3.0 otherwise 0.0.
|
||||
final double? elevation;
|
||||
|
||||
/// The color used for the drop shadow to indicate elevation.
|
||||
///
|
||||
/// If null, [NavigationBarThemeData.shadowColor] is used. If that
|
||||
/// is also null, the default value is [Colors.transparent] which
|
||||
/// indicates that no drop shadow will be displayed.
|
||||
///
|
||||
/// See [Material.shadowColor] for more details on drop shadows.
|
||||
final Color? shadowColor;
|
||||
|
||||
/// The color used as an overlay on [backgroundColor] to indicate elevation.
|
||||
///
|
||||
/// If null, [NavigationBarThemeData.surfaceTintColor] is used. If that
|
||||
@ -118,13 +135,6 @@ class NavigationBar extends StatelessWidget {
|
||||
/// overlay is applied.
|
||||
final Color? surfaceTintColor;
|
||||
|
||||
/// The elevation of the [NavigationBar] itself.
|
||||
///
|
||||
/// If null, [NavigationBarThemeData.elevation] is used. If that
|
||||
/// is also null, then if [ThemeData.useMaterial3] is true then it will
|
||||
/// be 3.0 otherwise 0.0.
|
||||
final double? elevation;
|
||||
|
||||
/// The height of the [NavigationBar] itself.
|
||||
///
|
||||
/// If this is used in [Scaffold.bottomNavigationBar] and the scaffold is
|
||||
@ -171,8 +181,9 @@ class NavigationBar extends StatelessWidget {
|
||||
color: backgroundColor
|
||||
?? navigationBarTheme.backgroundColor
|
||||
?? defaults.backgroundColor!,
|
||||
surfaceTintColor: surfaceTintColor ?? navigationBarTheme.surfaceTintColor ?? defaults.surfaceTintColor,
|
||||
elevation: elevation ?? navigationBarTheme.elevation ?? defaults.elevation!,
|
||||
shadowColor: shadowColor ?? navigationBarTheme.shadowColor ?? defaults.shadowColor,
|
||||
surfaceTintColor: surfaceTintColor ?? navigationBarTheme.surfaceTintColor ?? defaults.surfaceTintColor,
|
||||
child: SafeArea(
|
||||
child: SizedBox(
|
||||
height: effectiveHeight,
|
||||
@ -1250,6 +1261,8 @@ class _NavigationBarDefaultsM3 extends NavigationBarThemeData {
|
||||
|
||||
@override Color? get backgroundColor => _colors.surface;
|
||||
|
||||
@override Color? get shadowColor => Colors.transparent;
|
||||
|
||||
@override Color? get surfaceTintColor => _colors.surfaceTint;
|
||||
|
||||
@override MaterialStateProperty<IconThemeData?>? get iconTheme {
|
||||
|
@ -44,8 +44,9 @@ class NavigationBarThemeData with Diagnosticable {
|
||||
const NavigationBarThemeData({
|
||||
this.height,
|
||||
this.backgroundColor,
|
||||
this.surfaceTintColor,
|
||||
this.elevation,
|
||||
this.shadowColor,
|
||||
this.surfaceTintColor,
|
||||
this.indicatorColor,
|
||||
this.indicatorShape,
|
||||
this.labelTextStyle,
|
||||
@ -59,12 +60,15 @@ class NavigationBarThemeData with Diagnosticable {
|
||||
/// Overrides the default value of [NavigationBar.backgroundColor].
|
||||
final Color? backgroundColor;
|
||||
|
||||
/// Overrides the default value of [NavigationBar.surfaceTintColor].
|
||||
final Color? surfaceTintColor;
|
||||
|
||||
/// Overrides the default value of [NavigationBar.elevation].
|
||||
final double? elevation;
|
||||
|
||||
/// Overrides the default value of [NavigationBar.shadowColor].
|
||||
final Color? shadowColor;
|
||||
|
||||
/// Overrides the default value of [NavigationBar.surfaceTintColor].
|
||||
final Color? surfaceTintColor;
|
||||
|
||||
/// Overrides the default value of [NavigationBar]'s selection indicator.
|
||||
final Color? indicatorColor;
|
||||
|
||||
@ -92,8 +96,9 @@ class NavigationBarThemeData with Diagnosticable {
|
||||
NavigationBarThemeData copyWith({
|
||||
double? height,
|
||||
Color? backgroundColor,
|
||||
Color? surfaceTintColor,
|
||||
double? elevation,
|
||||
Color? shadowColor,
|
||||
Color? surfaceTintColor,
|
||||
Color? indicatorColor,
|
||||
ShapeBorder? indicatorShape,
|
||||
MaterialStateProperty<TextStyle?>? labelTextStyle,
|
||||
@ -103,8 +108,9 @@ class NavigationBarThemeData with Diagnosticable {
|
||||
return NavigationBarThemeData(
|
||||
height: height ?? this.height,
|
||||
backgroundColor: backgroundColor ?? this.backgroundColor,
|
||||
surfaceTintColor: surfaceTintColor ?? this.surfaceTintColor,
|
||||
elevation: elevation ?? this.elevation,
|
||||
shadowColor: shadowColor ?? this.shadowColor,
|
||||
surfaceTintColor: surfaceTintColor ?? this.surfaceTintColor,
|
||||
indicatorColor: indicatorColor ?? this.indicatorColor,
|
||||
indicatorShape: indicatorShape ?? this.indicatorShape,
|
||||
labelTextStyle: labelTextStyle ?? this.labelTextStyle,
|
||||
@ -126,8 +132,9 @@ class NavigationBarThemeData with Diagnosticable {
|
||||
return NavigationBarThemeData(
|
||||
height: lerpDouble(a?.height, b?.height, t),
|
||||
backgroundColor: Color.lerp(a?.backgroundColor, b?.backgroundColor, t),
|
||||
surfaceTintColor: Color.lerp(a?.surfaceTintColor, b?.surfaceTintColor, t),
|
||||
elevation: lerpDouble(a?.elevation, b?.elevation, t),
|
||||
shadowColor: Color.lerp(a?.shadowColor, b?.shadowColor, t),
|
||||
surfaceTintColor: Color.lerp(a?.surfaceTintColor, b?.surfaceTintColor, t),
|
||||
indicatorColor: Color.lerp(a?.indicatorColor, b?.indicatorColor, t),
|
||||
indicatorShape: ShapeBorder.lerp(a?.indicatorShape, b?.indicatorShape, t),
|
||||
labelTextStyle: MaterialStateProperty.lerp<TextStyle?>(a?.labelTextStyle, b?.labelTextStyle, t, TextStyle.lerp),
|
||||
@ -140,8 +147,9 @@ class NavigationBarThemeData with Diagnosticable {
|
||||
int get hashCode => Object.hash(
|
||||
height,
|
||||
backgroundColor,
|
||||
surfaceTintColor,
|
||||
elevation,
|
||||
shadowColor,
|
||||
surfaceTintColor,
|
||||
indicatorColor,
|
||||
indicatorShape,
|
||||
labelTextStyle,
|
||||
@ -160,8 +168,9 @@ class NavigationBarThemeData with Diagnosticable {
|
||||
return other is NavigationBarThemeData
|
||||
&& other.height == height
|
||||
&& other.backgroundColor == backgroundColor
|
||||
&& other.surfaceTintColor == surfaceTintColor
|
||||
&& other.elevation == elevation
|
||||
&& other.shadowColor == shadowColor
|
||||
&& other.surfaceTintColor == surfaceTintColor
|
||||
&& other.indicatorColor == indicatorColor
|
||||
&& other.indicatorShape == indicatorShape
|
||||
&& other.labelTextStyle == labelTextStyle
|
||||
@ -174,8 +183,9 @@ class NavigationBarThemeData with Diagnosticable {
|
||||
super.debugFillProperties(properties);
|
||||
properties.add(DoubleProperty('height', height, defaultValue: null));
|
||||
properties.add(ColorProperty('backgroundColor', backgroundColor, defaultValue: null));
|
||||
properties.add(ColorProperty('surfaceTintColor', surfaceTintColor, defaultValue: null));
|
||||
properties.add(DoubleProperty('elevation', elevation, defaultValue: null));
|
||||
properties.add(ColorProperty('shadowColor', shadowColor, defaultValue: null));
|
||||
properties.add(ColorProperty('surfaceTintColor', surfaceTintColor, defaultValue: null));
|
||||
properties.add(ColorProperty('indicatorColor', indicatorColor, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<ShapeBorder>('indicatorShape', indicatorShape, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<MaterialStateProperty<TextStyle?>>('labelTextStyle', labelTextStyle, defaultValue: null));
|
||||
|
@ -470,7 +470,7 @@ class _OutlinedButtonDefaultsM3 extends ButtonStyle {
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Color?>? get backgroundColor =>
|
||||
ButtonStyleButton.allOrNull<Color>(Colors.transparent);
|
||||
const MaterialStatePropertyAll<Color>(Colors.transparent);
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Color?>? get foregroundColor =>
|
||||
@ -496,27 +496,31 @@ class _OutlinedButtonDefaultsM3 extends ButtonStyle {
|
||||
return null;
|
||||
});
|
||||
|
||||
// No default shadow color
|
||||
@override
|
||||
MaterialStateProperty<Color>? get shadowColor =>
|
||||
const MaterialStatePropertyAll<Color>(Colors.transparent);
|
||||
|
||||
// No default surface tint color
|
||||
@override
|
||||
MaterialStateProperty<Color>? get surfaceTintColor =>
|
||||
const MaterialStatePropertyAll<Color>(Colors.transparent);
|
||||
|
||||
@override
|
||||
MaterialStateProperty<double>? get elevation =>
|
||||
ButtonStyleButton.allOrNull<double>(0.0);
|
||||
const MaterialStatePropertyAll<double>(0.0);
|
||||
|
||||
@override
|
||||
MaterialStateProperty<EdgeInsetsGeometry>? get padding =>
|
||||
ButtonStyleButton.allOrNull<EdgeInsetsGeometry>(_scaledPadding(context));
|
||||
MaterialStatePropertyAll<EdgeInsetsGeometry>(_scaledPadding(context));
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Size>? get minimumSize =>
|
||||
ButtonStyleButton.allOrNull<Size>(const Size(64.0, 40.0));
|
||||
const MaterialStatePropertyAll<Size>(Size(64.0, 40.0));
|
||||
|
||||
// No default fixedSize
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Size>? get maximumSize =>
|
||||
ButtonStyleButton.allOrNull<Size>(Size.infinite);
|
||||
const MaterialStatePropertyAll<Size>(Size.infinite);
|
||||
|
||||
@override
|
||||
MaterialStateProperty<BorderSide>? get side =>
|
||||
@ -529,7 +533,7 @@ class _OutlinedButtonDefaultsM3 extends ButtonStyle {
|
||||
|
||||
@override
|
||||
MaterialStateProperty<OutlinedBorder>? get shape =>
|
||||
ButtonStyleButton.allOrNull<OutlinedBorder>(const StadiumBorder());
|
||||
const MaterialStatePropertyAll<OutlinedBorder>(StadiumBorder());
|
||||
|
||||
@override
|
||||
MaterialStateProperty<MouseCursor?>? get mouseCursor =>
|
||||
|
@ -514,7 +514,7 @@ class _TextButtonDefaultsM3 extends ButtonStyle {
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Color?>? get backgroundColor =>
|
||||
ButtonStyleButton.allOrNull<Color>(Colors.transparent);
|
||||
const MaterialStatePropertyAll<Color>(Colors.transparent);
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Color?>? get foregroundColor =>
|
||||
@ -540,33 +540,37 @@ class _TextButtonDefaultsM3 extends ButtonStyle {
|
||||
return null;
|
||||
});
|
||||
|
||||
// No default shadow color
|
||||
@override
|
||||
MaterialStateProperty<Color>? get shadowColor =>
|
||||
const MaterialStatePropertyAll<Color>(Colors.transparent);
|
||||
|
||||
// No default surface tint color
|
||||
@override
|
||||
MaterialStateProperty<Color>? get surfaceTintColor =>
|
||||
const MaterialStatePropertyAll<Color>(Colors.transparent);
|
||||
|
||||
@override
|
||||
MaterialStateProperty<double>? get elevation =>
|
||||
ButtonStyleButton.allOrNull<double>(0.0);
|
||||
const MaterialStatePropertyAll<double>(0.0);
|
||||
|
||||
@override
|
||||
MaterialStateProperty<EdgeInsetsGeometry>? get padding =>
|
||||
ButtonStyleButton.allOrNull<EdgeInsetsGeometry>(_scaledPadding(context));
|
||||
MaterialStatePropertyAll<EdgeInsetsGeometry>(_scaledPadding(context));
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Size>? get minimumSize =>
|
||||
ButtonStyleButton.allOrNull<Size>(const Size(64.0, 40.0));
|
||||
const MaterialStatePropertyAll<Size>(Size(64.0, 40.0));
|
||||
|
||||
// No default fixedSize
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Size>? get maximumSize =>
|
||||
ButtonStyleButton.allOrNull<Size>(Size.infinite);
|
||||
const MaterialStatePropertyAll<Size>(Size.infinite);
|
||||
|
||||
// No default side
|
||||
|
||||
@override
|
||||
MaterialStateProperty<OutlinedBorder>? get shape =>
|
||||
ButtonStyleButton.allOrNull<OutlinedBorder>(const StadiumBorder());
|
||||
const MaterialStatePropertyAll<OutlinedBorder>(StadiumBorder());
|
||||
|
||||
@override
|
||||
MaterialStateProperty<MouseCursor?>? get mouseCursor =>
|
||||
|
@ -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: <Widget>[ ],
|
||||
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 {
|
||||
|
@ -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, <String>[
|
||||
'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: <Widget>[ ],
|
||||
);
|
||||
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 {
|
||||
|
@ -30,6 +30,8 @@ void main() {
|
||||
backgroundColor: Color(0x00000099),
|
||||
scrimColor: Color(0x00000098),
|
||||
elevation: 5.0,
|
||||
shadowColor: Color(0x00000097),
|
||||
surfaceTintColor: Color(0x00000096),
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(2.0))),
|
||||
width: 200.0,
|
||||
).debugFillProperties(builder);
|
||||
@ -43,6 +45,8 @@ void main() {
|
||||
'backgroundColor: Color(0x00000099)',
|
||||
'scrimColor: Color(0x00000098)',
|
||||
'elevation: 5.0',
|
||||
'shadowColor: Color(0x00000097)',
|
||||
'surfaceTintColor: Color(0x00000096)',
|
||||
'shape: RoundedRectangleBorder(BorderSide(width: 0.0, style: none), BorderRadius.circular(2.0))',
|
||||
'width: 200.0',
|
||||
]);
|
||||
@ -50,6 +54,7 @@ void main() {
|
||||
|
||||
testWidgets('Default values are used when no Drawer or DrawerThemeData properties are specified', (WidgetTester tester) async {
|
||||
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
|
||||
final bool useMaterial3 = ThemeData().useMaterial3;
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: Scaffold(
|
||||
@ -63,6 +68,8 @@ void main() {
|
||||
|
||||
expect(_drawerMaterial(tester).color, null);
|
||||
expect(_drawerMaterial(tester).elevation, 16.0);
|
||||
expect(_drawerMaterial(tester).shadowColor, useMaterial3 ? Colors.transparent : ThemeData().shadowColor);
|
||||
expect(_drawerMaterial(tester).surfaceTintColor, useMaterial3 ? ThemeData().colorScheme.surfaceTint : null);
|
||||
expect(_drawerMaterial(tester).shape, null);
|
||||
expect(_scrim(tester).color, Colors.black54);
|
||||
expect(_drawerRenderBox(tester).size.width, 304.0);
|
||||
@ -72,6 +79,8 @@ void main() {
|
||||
const Color backgroundColor = Color(0x00000001);
|
||||
const Color scrimColor = Color(0x00000002);
|
||||
const double elevation = 7.0;
|
||||
const Color shadowColor = Color(0x00000003);
|
||||
const Color surfaceTintColor = Color(0x00000004);
|
||||
const RoundedRectangleBorder shape = RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(16.0)));
|
||||
const double width = 200.0;
|
||||
|
||||
@ -83,6 +92,8 @@ void main() {
|
||||
backgroundColor: backgroundColor,
|
||||
scrimColor: scrimColor,
|
||||
elevation: elevation,
|
||||
shadowColor: shadowColor,
|
||||
surfaceTintColor: surfaceTintColor,
|
||||
shape: shape,
|
||||
width: width,
|
||||
),
|
||||
@ -98,6 +109,8 @@ void main() {
|
||||
|
||||
expect(_drawerMaterial(tester).color, backgroundColor);
|
||||
expect(_drawerMaterial(tester).elevation, elevation);
|
||||
expect(_drawerMaterial(tester).shadowColor, shadowColor);
|
||||
expect(_drawerMaterial(tester).surfaceTintColor, surfaceTintColor);
|
||||
expect(_drawerMaterial(tester).shape, shape);
|
||||
expect(_scrim(tester).color, scrimColor);
|
||||
expect(_drawerRenderBox(tester).size.width, width);
|
||||
@ -107,6 +120,8 @@ void main() {
|
||||
const Color backgroundColor = Color(0x00000001);
|
||||
const Color scrimColor = Color(0x00000002);
|
||||
const double elevation = 7.0;
|
||||
const Color shadowColor = Color(0x00000003);
|
||||
const Color surfaceTintColor = Color(0x00000004);
|
||||
const RoundedRectangleBorder shape = RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(16.0)));
|
||||
const double width = 200.0;
|
||||
|
||||
@ -115,8 +130,8 @@ void main() {
|
||||
MaterialApp(
|
||||
theme: ThemeData(
|
||||
drawerTheme: const DrawerThemeData(
|
||||
backgroundColor: Color(0x00000003),
|
||||
scrimColor: Color(0x00000004),
|
||||
backgroundColor: Color(0x00000005),
|
||||
scrimColor: Color(0x00000006),
|
||||
elevation: 13.0,
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(29.0))),
|
||||
width: 400.0,
|
||||
@ -128,6 +143,8 @@ void main() {
|
||||
drawer: const Drawer(
|
||||
backgroundColor: backgroundColor,
|
||||
elevation: elevation,
|
||||
shadowColor: shadowColor,
|
||||
surfaceTintColor: surfaceTintColor,
|
||||
shape: shape,
|
||||
width: width,
|
||||
),
|
||||
@ -139,6 +156,8 @@ void main() {
|
||||
|
||||
expect(_drawerMaterial(tester).color, backgroundColor);
|
||||
expect(_drawerMaterial(tester).elevation, elevation);
|
||||
expect(_drawerMaterial(tester).shadowColor, shadowColor);
|
||||
expect(_drawerMaterial(tester).surfaceTintColor, surfaceTintColor);
|
||||
expect(_drawerMaterial(tester).shape, shape);
|
||||
expect(_scrim(tester).color, scrimColor);
|
||||
expect(_drawerRenderBox(tester).size.width, width);
|
||||
@ -148,6 +167,8 @@ void main() {
|
||||
const Color backgroundColor = Color(0x00000001);
|
||||
const Color scrimColor = Color(0x00000002);
|
||||
const double elevation = 7.0;
|
||||
const Color shadowColor = Color(0x00000003);
|
||||
const Color surfaceTintColor = Color(0x00000004);
|
||||
const RoundedRectangleBorder shape = RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(16.0)));
|
||||
const double width = 200.0;
|
||||
|
||||
@ -156,9 +177,11 @@ void main() {
|
||||
MaterialApp(
|
||||
theme: ThemeData(
|
||||
drawerTheme: const DrawerThemeData(
|
||||
backgroundColor: Color(0x00000003),
|
||||
scrimColor: Color(0x00000004),
|
||||
backgroundColor: Color(0x00000005),
|
||||
scrimColor: Color(0x00000006),
|
||||
elevation: 13.0,
|
||||
shadowColor: Color(0x00000007),
|
||||
surfaceTintColor: Color(0x00000007),
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(29.0))),
|
||||
width: 400.0
|
||||
),
|
||||
@ -168,6 +191,8 @@ void main() {
|
||||
backgroundColor: backgroundColor,
|
||||
scrimColor: scrimColor,
|
||||
elevation: elevation,
|
||||
shadowColor: shadowColor,
|
||||
surfaceTintColor: surfaceTintColor,
|
||||
shape: shape,
|
||||
width: width,
|
||||
),
|
||||
@ -183,6 +208,8 @@ void main() {
|
||||
|
||||
expect(_drawerMaterial(tester).color, backgroundColor);
|
||||
expect(_drawerMaterial(tester).elevation, elevation);
|
||||
expect(_drawerMaterial(tester).shadowColor, shadowColor);
|
||||
expect(_drawerMaterial(tester).surfaceTintColor, surfaceTintColor);
|
||||
expect(_drawerMaterial(tester).shape, shape);
|
||||
expect(_scrim(tester).color, scrimColor);
|
||||
expect(_drawerRenderBox(tester).size.width, width);
|
||||
|
@ -1078,7 +1078,7 @@ void main() {
|
||||
expect(material.clipBehavior, Clip.none);
|
||||
expect(material.color, Colors.transparent);
|
||||
expect(material.elevation, 0.0);
|
||||
expect(material.shadowColor, null);
|
||||
expect(material.shadowColor, Colors.transparent);
|
||||
expect(material.shape, const StadiumBorder());
|
||||
expect(material.textStyle, null);
|
||||
expect(material.type, MaterialType.button);
|
||||
@ -1102,7 +1102,7 @@ void main() {
|
||||
expect(material.clipBehavior, Clip.none);
|
||||
expect(material.color, Colors.transparent);
|
||||
expect(material.elevation, 0.0);
|
||||
expect(material.shadowColor, null);
|
||||
expect(material.shadowColor, Colors.transparent);
|
||||
expect(material.shape, const StadiumBorder());
|
||||
expect(material.textStyle, null);
|
||||
expect(material.type, MaterialType.button);
|
||||
@ -1127,7 +1127,7 @@ void main() {
|
||||
expect(material.clipBehavior, Clip.none);
|
||||
expect(material.color, Colors.transparent);
|
||||
expect(material.elevation, 0.0);
|
||||
expect(material.shadowColor, null);
|
||||
expect(material.shadowColor, Colors.transparent);
|
||||
expect(material.shape, const StadiumBorder());
|
||||
expect(material.textStyle, null);
|
||||
expect(material.type, MaterialType.button);
|
||||
|
@ -32,7 +32,7 @@ void main() {
|
||||
expect(material.borderRadius, null);
|
||||
expect(material.color, Colors.transparent);
|
||||
expect(material.elevation, 0.0);
|
||||
expect(material.shadowColor, null);
|
||||
expect(material.shadowColor, Colors.transparent);
|
||||
expect(material.shape, const StadiumBorder());
|
||||
expect(material.textStyle, null);
|
||||
expect(material.type, MaterialType.button);
|
||||
@ -221,12 +221,12 @@ void main() {
|
||||
|
||||
await tester.pumpWidget(buildFrame());
|
||||
Material material = tester.widget<Material>(buttonMaterialFinder);
|
||||
expect(material.shadowColor, null); //default
|
||||
expect(material.shadowColor, Colors.transparent); //default
|
||||
|
||||
await tester.pumpWidget(buildFrame(overallShadowColor: shadowColor));
|
||||
await tester.pumpAndSettle(); // theme animation
|
||||
material = tester.widget<Material>(buttonMaterialFinder);
|
||||
expect(material.shadowColor, null);
|
||||
expect(material.shadowColor, Colors.transparent);
|
||||
|
||||
await tester.pumpWidget(buildFrame(themeShadowColor: shadowColor));
|
||||
await tester.pumpAndSettle(); // theme animation
|
||||
|
@ -189,6 +189,58 @@ void main() {
|
||||
expect(log, isEmpty);
|
||||
});
|
||||
|
||||
testWidgets('Shadow color defaults', (WidgetTester tester) async {
|
||||
Widget buildWithShadow(Color? shadowColor) {
|
||||
return Center(
|
||||
child: SizedBox(
|
||||
height: 100.0,
|
||||
width: 100.0,
|
||||
child: Material(
|
||||
shadowColor: shadowColor,
|
||||
elevation: 10,
|
||||
shape: const CircleBorder(),
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Default M2 shadow color
|
||||
await tester.pumpWidget(
|
||||
Theme(
|
||||
data: ThemeData(
|
||||
useMaterial3: false,
|
||||
),
|
||||
child: buildWithShadow(null),
|
||||
)
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
expect(getModel(tester).shadowColor, ThemeData().shadowColor);
|
||||
|
||||
// Default M3 shadow color
|
||||
await tester.pumpWidget(
|
||||
Theme(
|
||||
data: ThemeData(
|
||||
useMaterial3: true,
|
||||
),
|
||||
child: buildWithShadow(null),
|
||||
)
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
expect(getModel(tester).shadowColor, ThemeData().colorScheme.shadow);
|
||||
|
||||
// Drop shadow can be turned off with a transparent color.
|
||||
await tester.pumpWidget(
|
||||
Theme(
|
||||
data: ThemeData(
|
||||
useMaterial3: true,
|
||||
),
|
||||
child: buildWithShadow(Colors.transparent),
|
||||
)
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
expect(getModel(tester).shadowColor, Colors.transparent);
|
||||
});
|
||||
|
||||
testWidgets('Shadows animate smoothly', (WidgetTester tester) async {
|
||||
// This code verifies that the PhysicalModel's elevation animates over
|
||||
// a kThemeChangeDuration time interval.
|
||||
@ -304,6 +356,23 @@ void main() {
|
||||
final RenderPhysicalShape noTintModel = getModel(tester);
|
||||
expect(noTintModel.color, equals(baseColor));
|
||||
|
||||
// With transparent surfaceTintColor, it should not apply an overlay
|
||||
await tester.pumpWidget(
|
||||
Theme(
|
||||
data: ThemeData(
|
||||
useMaterial3: true,
|
||||
),
|
||||
child: buildMaterial(
|
||||
color: baseColor,
|
||||
surfaceTintColor: Colors.transparent,
|
||||
elevation: 12.0,
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
final RenderPhysicalShape transparentTintModel = getModel(tester);
|
||||
expect(transparentTintModel.color, equals(baseColor));
|
||||
|
||||
// With surfaceTintColor specified, it should not apply an overlay based
|
||||
// on the elevation.
|
||||
await tester.pumpWidget(
|
||||
|
Loading…
x
Reference in New Issue
Block a user