Add support for surface tint color overlays to Material
widget. (#100036)
This commit is contained in:
parent
e99a66a47e
commit
6ec0b83580
@ -21,6 +21,7 @@ import 'package:gen_defaults/dialog_template.dart';
|
|||||||
import 'package:gen_defaults/fab_template.dart';
|
import 'package:gen_defaults/fab_template.dart';
|
||||||
import 'package:gen_defaults/navigation_bar_template.dart';
|
import 'package:gen_defaults/navigation_bar_template.dart';
|
||||||
import 'package:gen_defaults/navigation_rail_template.dart';
|
import 'package:gen_defaults/navigation_rail_template.dart';
|
||||||
|
import 'package:gen_defaults/surface_tint.dart';
|
||||||
import 'package:gen_defaults/typography_template.dart';
|
import 'package:gen_defaults/typography_template.dart';
|
||||||
|
|
||||||
Map<String, dynamic> _readTokenFile(String fileName) {
|
Map<String, dynamic> _readTokenFile(String fileName) {
|
||||||
@ -70,9 +71,10 @@ Future<void> main(List<String> args) async {
|
|||||||
tokens['colorsLight'] = _readTokenFile('color_light.json');
|
tokens['colorsLight'] = _readTokenFile('color_light.json');
|
||||||
tokens['colorsDark'] = _readTokenFile('color_dark.json');
|
tokens['colorsDark'] = _readTokenFile('color_dark.json');
|
||||||
|
|
||||||
|
DialogTemplate('$materialLib/dialog.dart', tokens).updateFile();
|
||||||
FABTemplate('$materialLib/floating_action_button.dart', tokens).updateFile();
|
FABTemplate('$materialLib/floating_action_button.dart', tokens).updateFile();
|
||||||
NavigationBarTemplate('$materialLib/navigation_bar.dart', tokens).updateFile();
|
NavigationBarTemplate('$materialLib/navigation_bar.dart', tokens).updateFile();
|
||||||
NavigationRailTemplate('$materialLib/navigation_rail.dart', tokens).updateFile();
|
NavigationRailTemplate('$materialLib/navigation_rail.dart', tokens).updateFile();
|
||||||
|
SurfaceTintTemplate('$materialLib/elevation_overlay.dart', tokens).updateFile();
|
||||||
TypographyTemplate('$materialLib/typography.dart', tokens).updateFile();
|
TypographyTemplate('$materialLib/typography.dart', tokens).updateFile();
|
||||||
DialogTemplate('$materialLib/dialog.dart', tokens).updateFile();
|
|
||||||
}
|
}
|
||||||
|
27
dev/tools/gen_defaults/lib/surface_tint.dart
Normal file
27
dev/tools/gen_defaults/lib/surface_tint.dart
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
// Copyright 2014 The Flutter Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
import 'template.dart';
|
||||||
|
|
||||||
|
class SurfaceTintTemplate extends TokenTemplate {
|
||||||
|
const SurfaceTintTemplate(String fileName, Map<String, dynamic> tokens) : super(fileName, tokens);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String generate() => '''
|
||||||
|
// Generated version ${tokens["version"]}
|
||||||
|
|
||||||
|
// Surface tint opacities based on elevations according to the
|
||||||
|
// Material Design 3 specification:
|
||||||
|
// https://m3.material.io/styles/color/the-color-system/color-roles
|
||||||
|
// Ordered by increasing elevation.
|
||||||
|
const List<_ElevationOpacity> _surfaceTintElevationOpacities = <_ElevationOpacity>[
|
||||||
|
_ElevationOpacity(${tokens['md.sys.elevation.level0']}, 0.0), // Elevation level 0
|
||||||
|
_ElevationOpacity(${tokens['md.sys.elevation.level1']}, 0.05), // Elevation level 1
|
||||||
|
_ElevationOpacity(${tokens['md.sys.elevation.level2']}, 0.08), // Elevation level 2
|
||||||
|
_ElevationOpacity(${tokens['md.sys.elevation.level3']}, 0.11), // Elevation level 3
|
||||||
|
_ElevationOpacity(${tokens['md.sys.elevation.level4']}, 0.12), // Elevation level 4
|
||||||
|
_ElevationOpacity(${tokens['md.sys.elevation.level5']}, 0.14), // Elevation level 5
|
||||||
|
];
|
||||||
|
''';
|
||||||
|
}
|
@ -381,6 +381,8 @@ class _RawMaterialButtonState extends State<RawMaterialButton> with MaterialStat
|
|||||||
textStyle: widget.textStyle?.copyWith(color: effectiveTextColor),
|
textStyle: widget.textStyle?.copyWith(color: effectiveTextColor),
|
||||||
shape: effectiveShape,
|
shape: effectiveShape,
|
||||||
color: widget.fillColor,
|
color: widget.fillColor,
|
||||||
|
// For compatibility during the M3 migration the default shadow needs to be passed.
|
||||||
|
shadowColor: Theme.of(context).useMaterial3 ? Theme.of(context).shadowColor : null,
|
||||||
type: widget.fillColor == null ? MaterialType.transparency : MaterialType.button,
|
type: widget.fillColor == null ? MaterialType.transparency : MaterialType.button,
|
||||||
animationDuration: widget.animationDuration,
|
animationDuration: widget.animationDuration,
|
||||||
clipBehavior: widget.clipBehavior,
|
clipBehavior: widget.clipBehavior,
|
||||||
|
@ -9,15 +9,65 @@ import 'package:flutter/widgets.dart';
|
|||||||
import 'theme.dart';
|
import 'theme.dart';
|
||||||
|
|
||||||
/// A utility class for dealing with the overlay color needed
|
/// A utility class for dealing with the overlay color needed
|
||||||
/// to indicate elevation of surfaces in a dark theme.
|
/// to indicate elevation of surfaces.
|
||||||
class ElevationOverlay {
|
class ElevationOverlay {
|
||||||
// This class is not meant to be instantiated or extended; this constructor
|
// This class is not meant to be instantiated or extended; this constructor
|
||||||
// prevents instantiation and extension.
|
// prevents instantiation and extension.
|
||||||
ElevationOverlay._();
|
ElevationOverlay._();
|
||||||
|
|
||||||
|
/// Applies a surface tint color to a given container color to indicate
|
||||||
|
/// the level of its elevation.
|
||||||
|
///
|
||||||
|
/// With Material Design 3, some components will use a "surface tint" color
|
||||||
|
/// overlay with an opacity applied to their base color to indicate they are
|
||||||
|
/// 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.
|
||||||
|
static Color applySurfaceTint(Color color, Color? surfaceTint, double elevation) {
|
||||||
|
if (surfaceTint != null) {
|
||||||
|
return Color.alphaBlend(surfaceTint.withOpacity(_surfaceTintOpacityForElevation(elevation)), color);
|
||||||
|
}
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculates the opacity of the surface tint color from the elevation by
|
||||||
|
// looking it up in the token generated table of opacities, interpolating
|
||||||
|
// between values as needed. If the elevation is outside the range of values
|
||||||
|
// in the table it will clamp to the smallest or largest opacity.
|
||||||
|
static double _surfaceTintOpacityForElevation(double elevation) {
|
||||||
|
if (elevation < _surfaceTintElevationOpacities[0].elevation) {
|
||||||
|
// Elevation less than the first entry, so just clamp it to the first one.
|
||||||
|
return _surfaceTintElevationOpacities[0].opacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Walk the opacity list and find the closest match(es) for the elevation.
|
||||||
|
int index = 0;
|
||||||
|
while (elevation >= _surfaceTintElevationOpacities[index].elevation) {
|
||||||
|
// If we found it exactly or walked off the end of the list just return it.
|
||||||
|
if (elevation == _surfaceTintElevationOpacities[index].elevation ||
|
||||||
|
index + 1 == _surfaceTintElevationOpacities.length) {
|
||||||
|
return _surfaceTintElevationOpacities[index].opacity;
|
||||||
|
}
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interpolate between the two opacity values
|
||||||
|
final _ElevationOpacity lower = _surfaceTintElevationOpacities[index - 1];
|
||||||
|
final _ElevationOpacity upper = _surfaceTintElevationOpacities[index];
|
||||||
|
final double t = (elevation - lower.elevation) / (upper.elevation - lower.elevation);
|
||||||
|
return lower.opacity + t * (upper.opacity - lower.opacity);
|
||||||
|
}
|
||||||
|
|
||||||
/// Applies an overlay color to a surface color to indicate
|
/// Applies an overlay color to a surface color to indicate
|
||||||
/// the level of its elevation in a dark theme.
|
/// the level of its elevation in a dark theme.
|
||||||
///
|
///
|
||||||
|
/// If using Material Design 3, this type of color overlay is no longer used.
|
||||||
|
/// Instead a "surface tint" overlay is used instead. See [applySurfaceTint],
|
||||||
|
/// [ThemeData.useMaterial3] for more information.
|
||||||
|
///
|
||||||
/// Material drop shadows can be difficult to see in a dark theme, so the
|
/// Material drop shadows can be difficult to see in a dark theme, so the
|
||||||
/// elevation of a surface should be portrayed with an "overlay" in addition
|
/// elevation of a surface should be portrayed with an "overlay" in addition
|
||||||
/// to the shadow. As the elevation of the component increases, the
|
/// to the shadow. As the elevation of the component increases, the
|
||||||
@ -55,6 +105,10 @@ class ElevationOverlay {
|
|||||||
/// Computes the appropriate overlay color used to indicate elevation in
|
/// Computes the appropriate overlay color used to indicate elevation in
|
||||||
/// dark themes.
|
/// dark themes.
|
||||||
///
|
///
|
||||||
|
/// If using Material Design 3, this type of color overlay is no longer used.
|
||||||
|
/// Instead a "surface tint" overlay is used instead. See [applySurfaceTint],
|
||||||
|
/// [ThemeData.useMaterial3] for more information.
|
||||||
|
///
|
||||||
/// See also:
|
/// See also:
|
||||||
///
|
///
|
||||||
/// * https://material.io/design/color/dark-theme.html#properties which
|
/// * https://material.io/design/color/dark-theme.html#properties which
|
||||||
@ -67,6 +121,10 @@ class ElevationOverlay {
|
|||||||
/// Returns a color blended by laying a semi-transparent overlay (using the
|
/// Returns a color blended by laying a semi-transparent overlay (using the
|
||||||
/// [overlay] color) on top of a surface (using the [surface] color).
|
/// [overlay] color) on top of a surface (using the [surface] color).
|
||||||
///
|
///
|
||||||
|
/// If using Material Design 3, this type of color overlay is no longer used.
|
||||||
|
/// Instead a "surface tint" overlay is used instead. See [applySurfaceTint],
|
||||||
|
/// [ThemeData.useMaterial3] for more information.
|
||||||
|
///
|
||||||
/// The opacity of the overlay depends on [elevation]. As [elevation]
|
/// The opacity of the overlay depends on [elevation]. As [elevation]
|
||||||
/// increases, the opacity will also increase.
|
/// increases, the opacity will also increase.
|
||||||
///
|
///
|
||||||
@ -84,3 +142,34 @@ class ElevationOverlay {
|
|||||||
return color.withOpacity(opacity);
|
return color.withOpacity(opacity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A data class to hold the opacity at a given elevation.
|
||||||
|
class _ElevationOpacity {
|
||||||
|
const _ElevationOpacity(this.elevation, this.opacity);
|
||||||
|
|
||||||
|
final double elevation;
|
||||||
|
final double opacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
// BEGIN GENERATED TOKEN PROPERTIES
|
||||||
|
|
||||||
|
// Generated code to the end of this file. Do not edit by hand.
|
||||||
|
// These defaults are generated from the Material Design Token
|
||||||
|
// database by the script dev/tools/gen_defaults/bin/gen_defaults.dart.
|
||||||
|
|
||||||
|
// Generated version v0_90
|
||||||
|
|
||||||
|
// Surface tint opacities based on elevations according to the
|
||||||
|
// Material Design 3 specification:
|
||||||
|
// https://m3.material.io/styles/color/the-color-system/color-roles
|
||||||
|
// Ordered by increasing elevation.
|
||||||
|
const List<_ElevationOpacity> _surfaceTintElevationOpacities = <_ElevationOpacity>[
|
||||||
|
_ElevationOpacity(0.0, 0.0), // Elevation level 0
|
||||||
|
_ElevationOpacity(1.0, 0.05), // Elevation level 1
|
||||||
|
_ElevationOpacity(3.0, 0.08), // Elevation level 2
|
||||||
|
_ElevationOpacity(6.0, 0.11), // Elevation level 3
|
||||||
|
_ElevationOpacity(8.0, 0.12), // Elevation level 4
|
||||||
|
_ElevationOpacity(12.0, 0.14), // Elevation level 5
|
||||||
|
];
|
||||||
|
|
||||||
|
// END GENERATED TOKEN PROPERTIES
|
||||||
|
@ -111,10 +111,11 @@ abstract class MaterialInkController {
|
|||||||
///
|
///
|
||||||
/// In general, the features of a [Material] should not change over time (e.g. a
|
/// In general, the features of a [Material] should not change over time (e.g. a
|
||||||
/// [Material] should not change its [color], [shadowColor] or [type]).
|
/// [Material] should not change its [color], [shadowColor] or [type]).
|
||||||
/// Changes to [elevation] and [shadowColor] are animated for [animationDuration].
|
/// Changes to [elevation], [shadowColor] and [surfaceTintColor] are animated
|
||||||
/// Changes to [shape] are animated if [type] is not [MaterialType.transparency]
|
/// for [animationDuration]. Changes to [shape] are animated if [type] is
|
||||||
/// and [ShapeBorder.lerp] between the previous and next [shape] values is
|
/// not [MaterialType.transparency] and [ShapeBorder.lerp] between the previous
|
||||||
/// supported. Shape changes are also animated for [animationDuration].
|
/// and next [shape] values is supported. Shape changes are also animated
|
||||||
|
/// for [animationDuration].
|
||||||
///
|
///
|
||||||
/// ## Shape
|
/// ## Shape
|
||||||
///
|
///
|
||||||
@ -166,7 +167,7 @@ abstract class MaterialInkController {
|
|||||||
class Material extends StatefulWidget {
|
class Material extends StatefulWidget {
|
||||||
/// Creates a piece of material.
|
/// Creates a piece of material.
|
||||||
///
|
///
|
||||||
/// The [type], [elevation], [shadowColor], [borderOnForeground],
|
/// The [type], [elevation], [borderOnForeground],
|
||||||
/// [clipBehavior], and [animationDuration] arguments must not be null.
|
/// [clipBehavior], and [animationDuration] arguments must not be null.
|
||||||
/// Additionally, [elevation] must be non-negative.
|
/// Additionally, [elevation] must be non-negative.
|
||||||
///
|
///
|
||||||
@ -181,6 +182,7 @@ class Material extends StatefulWidget {
|
|||||||
this.elevation = 0.0,
|
this.elevation = 0.0,
|
||||||
this.color,
|
this.color,
|
||||||
this.shadowColor,
|
this.shadowColor,
|
||||||
|
this.surfaceTintColor,
|
||||||
this.textStyle,
|
this.textStyle,
|
||||||
this.borderRadius,
|
this.borderRadius,
|
||||||
this.shape,
|
this.shape,
|
||||||
@ -217,16 +219,20 @@ class Material extends StatefulWidget {
|
|||||||
/// widget conceptually defines an independent printed piece of material.
|
/// widget conceptually defines an independent printed piece of material.
|
||||||
///
|
///
|
||||||
/// Defaults to 0. Changing this value will cause the shadow and the elevation
|
/// Defaults to 0. Changing this value will cause the shadow and the elevation
|
||||||
/// overlay to animate over [Material.animationDuration].
|
/// overlay or surface tint to animate over [Material.animationDuration].
|
||||||
///
|
///
|
||||||
/// The value is non-negative.
|
/// The value is non-negative.
|
||||||
///
|
///
|
||||||
/// See also:
|
/// See also:
|
||||||
///
|
///
|
||||||
|
/// * [ThemeData.useMaterial3] which defines whether a surface tint or
|
||||||
|
/// elevation overlay is used to indicate elevation.
|
||||||
/// * [ThemeData.applyElevationOverlayColor] which controls the whether
|
/// * [ThemeData.applyElevationOverlayColor] which controls the whether
|
||||||
/// an overlay color will be applied to indicate elevation.
|
/// an overlay color will be applied to indicate elevation.
|
||||||
/// * [Material.color] which may have an elevation overlay applied.
|
/// * [Material.color] which may have an elevation overlay applied.
|
||||||
///
|
/// * [Material.shadowColor] which will be used for the color of a drop shadow.
|
||||||
|
/// * [Material.surfaceTintColor] which will be used as the overlay tint to
|
||||||
|
/// show elevation.
|
||||||
/// {@endtemplate}
|
/// {@endtemplate}
|
||||||
final double elevation;
|
final double elevation;
|
||||||
|
|
||||||
@ -235,29 +241,59 @@ class Material extends StatefulWidget {
|
|||||||
/// Must be opaque. To create a transparent piece of material, use
|
/// Must be opaque. To create a transparent piece of material, use
|
||||||
/// [MaterialType.transparency].
|
/// [MaterialType.transparency].
|
||||||
///
|
///
|
||||||
/// To support dark themes, if the surrounding
|
/// If [ThemeData.useMaterial3] is true then an optional [surfaceTintColor]
|
||||||
/// [ThemeData.applyElevationOverlayColor] is true and [ThemeData.brightness]
|
/// overlay may be applied on top of this color to indicate elevation.
|
||||||
/// is [Brightness.dark] then a semi-transparent overlay color will be
|
///
|
||||||
/// composited on top of this color to indicate the elevation.
|
/// If [ThemeData.useMaterial3] is false and [ThemeData.applyElevationOverlayColor]
|
||||||
|
/// is true and [ThemeData.brightness] is [Brightness.dark] then a
|
||||||
|
/// semi-transparent overlay color will be composited on top of this
|
||||||
|
/// color to indicate the elevation. This is no longer needed for Material
|
||||||
|
/// Design 3, which uses [surfaceTintColor].
|
||||||
///
|
///
|
||||||
/// By default, the color is derived from the [type] of material.
|
/// By default, the color is derived from the [type] of material.
|
||||||
final Color? color;
|
final Color? color;
|
||||||
|
|
||||||
/// The color to paint the shadow below the material.
|
/// The color to paint the shadow below the material.
|
||||||
///
|
///
|
||||||
/// If null, [ThemeData.shadowColor] is used, which defaults to fully opaque black.
|
/// 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.
|
||||||
///
|
///
|
||||||
/// Shadows can be difficult to see in a dark theme, so the elevation of a
|
/// When [ThemeData.useMaterial3] is false, and this is null, then
|
||||||
/// surface should be portrayed with an "overlay" in addition to the shadow.
|
/// [ThemeData.shadowColor] is used, which defaults to fully opaque black.
|
||||||
/// As the elevation of the component increases, the overlay increases in
|
|
||||||
/// opacity.
|
|
||||||
///
|
///
|
||||||
/// See also:
|
/// See also:
|
||||||
///
|
/// * [ThemeData.useMaterial3], which determines the default value for this
|
||||||
|
/// property if it is null.
|
||||||
/// * [ThemeData.applyElevationOverlayColor], which turns elevation overlay
|
/// * [ThemeData.applyElevationOverlayColor], which turns elevation overlay
|
||||||
/// on or off for dark themes.
|
/// on or off for dark themes.
|
||||||
final Color? shadowColor;
|
final Color? shadowColor;
|
||||||
|
|
||||||
|
/// The color of the surface tint overlay applied to the material color
|
||||||
|
/// to indicate elevation.
|
||||||
|
///
|
||||||
|
/// Material Design 3 introduced a new way for some components to indicate
|
||||||
|
/// their elevation by using a surface tint color overlay on top of the
|
||||||
|
/// base material [color]. This overlay is painted with an opacity that is
|
||||||
|
/// related to the [elevation] of the material.
|
||||||
|
///
|
||||||
|
/// 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].
|
||||||
|
///
|
||||||
|
/// Otherwise, no surface tint will be applied.
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [ThemeData.useMaterial3], which turns this feature on.
|
||||||
|
/// * [ElevationOverlay.applySurfaceTint], which is used to implement the
|
||||||
|
/// tint.
|
||||||
|
/// * https://m3.material.io/styles/color/the-color-system/color-roles
|
||||||
|
/// which specifies how the overlay is applied.
|
||||||
|
final Color? surfaceTintColor;
|
||||||
|
|
||||||
/// The typographical style to use for text within this material.
|
/// The typographical style to use for text within this material.
|
||||||
final TextStyle? textStyle;
|
final TextStyle? textStyle;
|
||||||
|
|
||||||
@ -287,7 +323,7 @@ class Material extends StatefulWidget {
|
|||||||
final Clip clipBehavior;
|
final Clip clipBehavior;
|
||||||
|
|
||||||
/// Defines the duration of animated changes for [shape], [elevation],
|
/// Defines the duration of animated changes for [shape], [elevation],
|
||||||
/// [shadowColor] and the elevation overlay if it is applied.
|
/// [shadowColor], [surfaceTintColor] and the elevation overlay if it is applied.
|
||||||
///
|
///
|
||||||
/// The default value is [kThemeChangeDuration].
|
/// The default value is [kThemeChangeDuration].
|
||||||
final Duration animationDuration;
|
final Duration animationDuration;
|
||||||
@ -327,6 +363,7 @@ class Material extends StatefulWidget {
|
|||||||
properties.add(DoubleProperty('elevation', elevation, defaultValue: 0.0));
|
properties.add(DoubleProperty('elevation', elevation, defaultValue: 0.0));
|
||||||
properties.add(ColorProperty('color', color, defaultValue: null));
|
properties.add(ColorProperty('color', color, defaultValue: null));
|
||||||
properties.add(ColorProperty('shadowColor', shadowColor, defaultValue: null));
|
properties.add(ColorProperty('shadowColor', shadowColor, defaultValue: null));
|
||||||
|
properties.add(ColorProperty('surfaceTintColor', surfaceTintColor, defaultValue: null));
|
||||||
textStyle?.debugFillProperties(properties, prefix: 'textStyle.');
|
textStyle?.debugFillProperties(properties, prefix: 'textStyle.');
|
||||||
properties.add(DiagnosticsProperty<ShapeBorder>('shape', shape, defaultValue: null));
|
properties.add(DiagnosticsProperty<ShapeBorder>('shape', shape, defaultValue: null));
|
||||||
properties.add(DiagnosticsProperty<bool>('borderOnForeground', borderOnForeground, defaultValue: true));
|
properties.add(DiagnosticsProperty<bool>('borderOnForeground', borderOnForeground, defaultValue: true));
|
||||||
@ -362,6 +399,7 @@ class _MaterialState extends State<Material> with TickerProviderStateMixin {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final ThemeData theme = Theme.of(context);
|
||||||
final Color? backgroundColor = _getBackgroundColor(context);
|
final Color? backgroundColor = _getBackgroundColor(context);
|
||||||
assert(
|
assert(
|
||||||
backgroundColor != null || widget.type == MaterialType.transparency,
|
backgroundColor != null || widget.type == MaterialType.transparency,
|
||||||
@ -403,14 +441,18 @@ class _MaterialState extends State<Material> with TickerProviderStateMixin {
|
|||||||
// we choose not to as we want the change from the fast-path to the
|
// we choose not to as we want the change from the fast-path to the
|
||||||
// slow-path to be noticeable in the construction site of Material.
|
// slow-path to be noticeable in the construction site of Material.
|
||||||
if (widget.type == MaterialType.canvas && widget.shape == null && widget.borderRadius == null) {
|
if (widget.type == MaterialType.canvas && widget.shape == null && widget.borderRadius == null) {
|
||||||
|
final Color color = Theme.of(context).useMaterial3
|
||||||
|
? ElevationOverlay.applySurfaceTint(backgroundColor!, widget.surfaceTintColor, widget.elevation)
|
||||||
|
: ElevationOverlay.applyOverlay(context, backgroundColor!, widget.elevation);
|
||||||
|
|
||||||
return AnimatedPhysicalModel(
|
return AnimatedPhysicalModel(
|
||||||
curve: Curves.fastOutSlowIn,
|
curve: Curves.fastOutSlowIn,
|
||||||
duration: widget.animationDuration,
|
duration: widget.animationDuration,
|
||||||
shape: BoxShape.rectangle,
|
shape: BoxShape.rectangle,
|
||||||
clipBehavior: widget.clipBehavior,
|
clipBehavior: widget.clipBehavior,
|
||||||
elevation: widget.elevation,
|
elevation: widget.elevation,
|
||||||
color: ElevationOverlay.applyOverlay(context, backgroundColor!, widget.elevation),
|
color: color,
|
||||||
shadowColor: widget.shadowColor ?? Theme.of(context).shadowColor,
|
shadowColor: widget.shadowColor ?? (theme.useMaterial3 ? const Color(0x00000000) : theme.shadowColor),
|
||||||
animateColor: false,
|
animateColor: false,
|
||||||
child: contents,
|
child: contents,
|
||||||
);
|
);
|
||||||
@ -435,7 +477,8 @@ class _MaterialState extends State<Material> with TickerProviderStateMixin {
|
|||||||
clipBehavior: widget.clipBehavior,
|
clipBehavior: widget.clipBehavior,
|
||||||
elevation: widget.elevation,
|
elevation: widget.elevation,
|
||||||
color: backgroundColor!,
|
color: backgroundColor!,
|
||||||
shadowColor: widget.shadowColor ?? Theme.of(context).shadowColor,
|
shadowColor: widget.shadowColor ?? (theme.useMaterial3 ? const Color(0x00000000) : theme.shadowColor),
|
||||||
|
surfaceTintColor: widget.surfaceTintColor,
|
||||||
child: contents,
|
child: contents,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -694,6 +737,7 @@ class _MaterialInterior extends ImplicitlyAnimatedWidget {
|
|||||||
required this.elevation,
|
required this.elevation,
|
||||||
required this.color,
|
required this.color,
|
||||||
required this.shadowColor,
|
required this.shadowColor,
|
||||||
|
required this.surfaceTintColor,
|
||||||
Curve curve = Curves.linear,
|
Curve curve = Curves.linear,
|
||||||
required Duration duration,
|
required Duration duration,
|
||||||
}) : assert(child != null),
|
}) : assert(child != null),
|
||||||
@ -738,6 +782,9 @@ class _MaterialInterior extends ImplicitlyAnimatedWidget {
|
|||||||
/// The target shadow color.
|
/// The target shadow color.
|
||||||
final Color shadowColor;
|
final Color shadowColor;
|
||||||
|
|
||||||
|
/// The target surface tint color.
|
||||||
|
final Color? surfaceTintColor;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_MaterialInteriorState createState() => _MaterialInteriorState();
|
_MaterialInteriorState createState() => _MaterialInteriorState();
|
||||||
|
|
||||||
@ -753,6 +800,7 @@ class _MaterialInterior extends ImplicitlyAnimatedWidget {
|
|||||||
|
|
||||||
class _MaterialInteriorState extends AnimatedWidgetBaseState<_MaterialInterior> {
|
class _MaterialInteriorState extends AnimatedWidgetBaseState<_MaterialInterior> {
|
||||||
Tween<double>? _elevation;
|
Tween<double>? _elevation;
|
||||||
|
ColorTween? _surfaceTintColor;
|
||||||
ColorTween? _shadowColor;
|
ColorTween? _shadowColor;
|
||||||
ShapeBorderTween? _border;
|
ShapeBorderTween? _border;
|
||||||
|
|
||||||
@ -768,6 +816,13 @@ class _MaterialInteriorState extends AnimatedWidgetBaseState<_MaterialInterior>
|
|||||||
widget.shadowColor,
|
widget.shadowColor,
|
||||||
(dynamic value) => ColorTween(begin: value as Color),
|
(dynamic value) => ColorTween(begin: value as Color),
|
||||||
) as ColorTween?;
|
) as ColorTween?;
|
||||||
|
_surfaceTintColor = widget.surfaceTintColor != null
|
||||||
|
? visitor(
|
||||||
|
_surfaceTintColor,
|
||||||
|
widget.surfaceTintColor,
|
||||||
|
(dynamic value) => ColorTween(begin: value as Color),
|
||||||
|
) as ColorTween?
|
||||||
|
: null;
|
||||||
_border = visitor(
|
_border = visitor(
|
||||||
_border,
|
_border,
|
||||||
widget.shape,
|
widget.shape,
|
||||||
@ -779,6 +834,9 @@ class _MaterialInteriorState extends AnimatedWidgetBaseState<_MaterialInterior>
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final ShapeBorder shape = _border!.evaluate(animation)!;
|
final ShapeBorder shape = _border!.evaluate(animation)!;
|
||||||
final double elevation = _elevation!.evaluate(animation);
|
final double elevation = _elevation!.evaluate(animation);
|
||||||
|
final Color color = Theme.of(context).useMaterial3
|
||||||
|
? ElevationOverlay.applySurfaceTint(widget.color, _surfaceTintColor?.evaluate(animation), elevation)
|
||||||
|
: ElevationOverlay.applyOverlay(context, widget.color, elevation);
|
||||||
return PhysicalShape(
|
return PhysicalShape(
|
||||||
clipper: ShapeBorderClipper(
|
clipper: ShapeBorderClipper(
|
||||||
shape: shape,
|
shape: shape,
|
||||||
@ -786,7 +844,7 @@ class _MaterialInteriorState extends AnimatedWidgetBaseState<_MaterialInterior>
|
|||||||
),
|
),
|
||||||
clipBehavior: widget.clipBehavior,
|
clipBehavior: widget.clipBehavior,
|
||||||
elevation: elevation,
|
elevation: elevation,
|
||||||
color: ElevationOverlay.applyOverlay(context, widget.color, elevation),
|
color: color,
|
||||||
shadowColor: _shadowColor!.evaluate(animation)!,
|
shadowColor: _shadowColor!.evaluate(animation)!,
|
||||||
child: _ShapeBorderPaint(
|
child: _ShapeBorderPaint(
|
||||||
shape: shape,
|
shape: shape,
|
||||||
|
@ -437,7 +437,7 @@ class ThemeData with Diagnosticable {
|
|||||||
dialogBackgroundColor ??= colorScheme.background;
|
dialogBackgroundColor ??= colorScheme.background;
|
||||||
indicatorColor ??= onPrimarySurfaceColor;
|
indicatorColor ??= onPrimarySurfaceColor;
|
||||||
errorColor ??= colorScheme.error;
|
errorColor ??= colorScheme.error;
|
||||||
applyElevationOverlayColor ??= isDark;
|
applyElevationOverlayColor ??= brightness == Brightness.dark;
|
||||||
}
|
}
|
||||||
applyElevationOverlayColor ??= false;
|
applyElevationOverlayColor ??= false;
|
||||||
primarySwatch ??= Colors.blue;
|
primarySwatch ??= Colors.blue;
|
||||||
@ -922,6 +922,7 @@ class ThemeData with Diagnosticable {
|
|||||||
factory ThemeData.from({
|
factory ThemeData.from({
|
||||||
required ColorScheme colorScheme,
|
required ColorScheme colorScheme,
|
||||||
TextTheme? textTheme,
|
TextTheme? textTheme,
|
||||||
|
bool? useMaterial3,
|
||||||
}) {
|
}) {
|
||||||
final bool isDark = colorScheme.brightness == Brightness.dark;
|
final bool isDark = colorScheme.brightness == Brightness.dark;
|
||||||
|
|
||||||
@ -947,6 +948,7 @@ class ThemeData with Diagnosticable {
|
|||||||
errorColor: colorScheme.error,
|
errorColor: colorScheme.error,
|
||||||
textTheme: textTheme,
|
textTheme: textTheme,
|
||||||
applyElevationOverlayColor: isDark,
|
applyElevationOverlayColor: isDark,
|
||||||
|
useMaterial3: useMaterial3,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1003,6 +1005,11 @@ class ThemeData with Diagnosticable {
|
|||||||
/// Apply a semi-transparent overlay color on Material surfaces to indicate
|
/// Apply a semi-transparent overlay color on Material surfaces to indicate
|
||||||
/// elevation for dark themes.
|
/// elevation for dark themes.
|
||||||
///
|
///
|
||||||
|
/// If [useMaterial3] is true, then this flag is ignored as there is a new
|
||||||
|
/// [Material.surfaceTintColor] used to create an overlay for Material 3.
|
||||||
|
/// This flag is meant only for the Material 2 elevation overlay for dark
|
||||||
|
/// themes.
|
||||||
|
///
|
||||||
/// Material drop shadows can be difficult to see in a dark theme, so the
|
/// Material drop shadows can be difficult to see in a dark theme, so the
|
||||||
/// elevation of a surface should be portrayed with an "overlay" in addition
|
/// elevation of a surface should be portrayed with an "overlay" in addition
|
||||||
/// to the shadow. As the elevation of the component increases, the
|
/// to the shadow. As the elevation of the component increases, the
|
||||||
@ -1161,6 +1168,7 @@ class ThemeData with Diagnosticable {
|
|||||||
/// * [AlertDialog]
|
/// * [AlertDialog]
|
||||||
/// * [Dialog]
|
/// * [Dialog]
|
||||||
/// * [FloatingActionButton]
|
/// * [FloatingActionButton]
|
||||||
|
/// * [Material]
|
||||||
/// * [NavigationBar]
|
/// * [NavigationBar]
|
||||||
/// * [NavigationRail]
|
/// * [NavigationRail]
|
||||||
///
|
///
|
||||||
|
88
packages/flutter/test/material/elevation_overlay_test.dart
Normal file
88
packages/flutter/test/material/elevation_overlay_test.dart
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
// Copyright 2014 The Flutter Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
test('applySurfaceTint with null surface tint returns given color', () {
|
||||||
|
final Color result = ElevationOverlay.applySurfaceTint(const Color(0xff888888), null, 42.0);
|
||||||
|
|
||||||
|
expect(result, equals(const Color(0xFF888888)));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('applySurfaceTint with exact elevation levels uses the right opacity overlay', () {
|
||||||
|
const Color baseColor = Color(0xff888888);
|
||||||
|
const Color surfaceTintColor = Color(0xff44CCFF);
|
||||||
|
|
||||||
|
Color overlayWithOpacity(double opacity) {
|
||||||
|
return Color.alphaBlend(surfaceTintColor.withOpacity(opacity), baseColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Based on values from the spec:
|
||||||
|
// https://m3.material.io/styles/color/the-color-system/color-roles
|
||||||
|
|
||||||
|
// Elevation level 0 (0.0) - should have opacity 0.0.
|
||||||
|
expect(ElevationOverlay.applySurfaceTint(baseColor, surfaceTintColor, 0.0), equals(overlayWithOpacity(0.0)));
|
||||||
|
|
||||||
|
// Elevation level 1 (1.0) - should have opacity 0.05.
|
||||||
|
expect(ElevationOverlay.applySurfaceTint(baseColor, surfaceTintColor, 1.0), equals(overlayWithOpacity(0.05)));
|
||||||
|
|
||||||
|
// Elevation level 2 (3.0) - should have opacity 0.08.
|
||||||
|
expect(ElevationOverlay.applySurfaceTint(baseColor, surfaceTintColor, 3.0), equals(overlayWithOpacity(0.08)));
|
||||||
|
|
||||||
|
// Elevation level 3 (6.0) - should have opacity 0.11`.
|
||||||
|
expect(ElevationOverlay.applySurfaceTint(baseColor, surfaceTintColor, 6.0), equals(overlayWithOpacity(0.11)));
|
||||||
|
|
||||||
|
// Elevation level 4 (8.0) - should have opacity 0.12.
|
||||||
|
expect(ElevationOverlay.applySurfaceTint(baseColor, surfaceTintColor, 8.0), equals(overlayWithOpacity(0.12)));
|
||||||
|
|
||||||
|
// Elevation level 5 (12.0) - should have opacity 0.14.
|
||||||
|
expect(ElevationOverlay.applySurfaceTint(baseColor, surfaceTintColor, 12.0), equals(overlayWithOpacity(0.14)));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('applySurfaceTint with elevation lower than level 0 should have no overlay', () {
|
||||||
|
const Color baseColor = Color(0xff888888);
|
||||||
|
const Color surfaceTintColor = Color(0xff44CCFF);
|
||||||
|
|
||||||
|
Color overlayWithOpacity(double opacity) {
|
||||||
|
return Color.alphaBlend(surfaceTintColor.withOpacity(opacity), baseColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(ElevationOverlay.applySurfaceTint(baseColor, surfaceTintColor, -42.0), equals(overlayWithOpacity(0.0)));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('applySurfaceTint with elevation higher than level 5 should have no level 5 overlay', () {
|
||||||
|
const Color baseColor = Color(0xff888888);
|
||||||
|
const Color surfaceTintColor = Color(0xff44CCFF);
|
||||||
|
|
||||||
|
Color overlayWithOpacity(double opacity) {
|
||||||
|
return Color.alphaBlend(surfaceTintColor.withOpacity(opacity), baseColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Elevation level 5 (12.0) - should have opacity 0.14.
|
||||||
|
expect(ElevationOverlay.applySurfaceTint(baseColor, surfaceTintColor, 42.0), equals(overlayWithOpacity(0.14)));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('applySurfaceTint with elevation between two levels should interpolate the opacity', () {
|
||||||
|
const Color baseColor = Color(0xff888888);
|
||||||
|
const Color surfaceTintColor = Color(0xff44CCFF);
|
||||||
|
|
||||||
|
Color overlayWithOpacity(double opacity) {
|
||||||
|
return Color.alphaBlend(surfaceTintColor.withOpacity(opacity), baseColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Elevation between level 4 (8.0) and level 5 (12.0) should be interpolated
|
||||||
|
// between the opacities 0.12 and 0.14.
|
||||||
|
|
||||||
|
// One third (0.3): (elevation 9.2) -> (opacity 0.126)
|
||||||
|
expect(ElevationOverlay.applySurfaceTint(baseColor, surfaceTintColor, 9.2), equals(overlayWithOpacity(0.126)));
|
||||||
|
|
||||||
|
// Half way (0.5): (elevation 10.0) -> (opacity 0.13)
|
||||||
|
expect(ElevationOverlay.applySurfaceTint(baseColor, surfaceTintColor, 10.0), equals(overlayWithOpacity(0.13)));
|
||||||
|
|
||||||
|
// Two thirds (0.6): (elevation 10.4) -> (opacity 0.132)
|
||||||
|
expect(ElevationOverlay.applySurfaceTint(baseColor, surfaceTintColor, 10.4), equals(overlayWithOpacity(0.132)));
|
||||||
|
});
|
||||||
|
}
|
@ -25,6 +25,7 @@ class NotifyMaterial extends StatelessWidget {
|
|||||||
Widget buildMaterial({
|
Widget buildMaterial({
|
||||||
double elevation = 0.0,
|
double elevation = 0.0,
|
||||||
Color shadowColor = const Color(0xFF00FF00),
|
Color shadowColor = const Color(0xFF00FF00),
|
||||||
|
Color? surfaceTintColor,
|
||||||
Color color = const Color(0xFF0000FF),
|
Color color = const Color(0xFF0000FF),
|
||||||
}) {
|
}) {
|
||||||
return Center(
|
return Center(
|
||||||
@ -34,6 +35,7 @@ Widget buildMaterial({
|
|||||||
child: Material(
|
child: Material(
|
||||||
color: color,
|
color: color,
|
||||||
shadowColor: shadowColor,
|
shadowColor: shadowColor,
|
||||||
|
surfaceTintColor: surfaceTintColor,
|
||||||
elevation: elevation,
|
elevation: elevation,
|
||||||
shape: const CircleBorder(),
|
shape: const CircleBorder(),
|
||||||
),
|
),
|
||||||
@ -99,6 +101,7 @@ void main() {
|
|||||||
const Material(
|
const Material(
|
||||||
color: Color(0xFFFFFFFF),
|
color: Color(0xFFFFFFFF),
|
||||||
shadowColor: Color(0xffff0000),
|
shadowColor: Color(0xffff0000),
|
||||||
|
surfaceTintColor: Color(0xff0000ff),
|
||||||
textStyle: TextStyle(color: Color(0xff00ff00)),
|
textStyle: TextStyle(color: Color(0xff00ff00)),
|
||||||
borderRadius: BorderRadiusDirectional.all(Radius.circular(10)),
|
borderRadius: BorderRadiusDirectional.all(Radius.circular(10)),
|
||||||
).debugFillProperties(builder);
|
).debugFillProperties(builder);
|
||||||
@ -112,6 +115,7 @@ void main() {
|
|||||||
'type: canvas',
|
'type: canvas',
|
||||||
'color: Color(0xffffffff)',
|
'color: Color(0xffffffff)',
|
||||||
'shadowColor: Color(0xffff0000)',
|
'shadowColor: Color(0xffff0000)',
|
||||||
|
'surfaceTintColor: Color(0xff0000ff)',
|
||||||
'textStyle.inherit: true',
|
'textStyle.inherit: true',
|
||||||
'textStyle.color: Color(0xff00ff00)',
|
'textStyle.color: Color(0xff00ff00)',
|
||||||
'borderRadius: BorderRadiusDirectional.circular(10.0)',
|
'borderRadius: BorderRadiusDirectional.circular(10.0)',
|
||||||
@ -265,12 +269,72 @@ void main() {
|
|||||||
expect(pressed, isTrue);
|
expect(pressed, isTrue);
|
||||||
});
|
});
|
||||||
|
|
||||||
group('Elevation Overlay', () {
|
group('Surface Tint Overlay', () {
|
||||||
|
testWidgets('applyElevationOverlayColor does not effect anything with useMaterial3 set to true', (WidgetTester tester) async {
|
||||||
|
const Color surfaceColor = Color(0xFF121212);
|
||||||
|
await tester.pumpWidget(Theme(
|
||||||
|
data: ThemeData(
|
||||||
|
useMaterial3: true,
|
||||||
|
applyElevationOverlayColor: true,
|
||||||
|
colorScheme: const ColorScheme.dark().copyWith(surface: surfaceColor),
|
||||||
|
),
|
||||||
|
child: buildMaterial(color: surfaceColor, elevation: 8.0),
|
||||||
|
));
|
||||||
|
final RenderPhysicalShape model = getModel(tester);
|
||||||
|
expect(model.color, equals(surfaceColor));
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('surfaceTintColor is used to as an overlay to indicate elevation', (WidgetTester tester) async {
|
||||||
|
const Color baseColor = Color(0xFF121212);
|
||||||
|
const Color surfaceTintColor = Color(0xff44CCFF);
|
||||||
|
|
||||||
|
// With no surfaceTintColor specified, it should not apply an overlay
|
||||||
|
await tester.pumpWidget(
|
||||||
|
Theme(
|
||||||
|
data: ThemeData(
|
||||||
|
useMaterial3: true,
|
||||||
|
),
|
||||||
|
child: buildMaterial(
|
||||||
|
color: baseColor,
|
||||||
|
elevation: 12.0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
final RenderPhysicalShape noTintModel = getModel(tester);
|
||||||
|
expect(noTintModel.color, equals(baseColor));
|
||||||
|
|
||||||
|
// With surfaceTintColor specified, it should not apply an overlay based
|
||||||
|
// on the elevation.
|
||||||
|
await tester.pumpWidget(
|
||||||
|
Theme(
|
||||||
|
data: ThemeData(
|
||||||
|
useMaterial3: true,
|
||||||
|
),
|
||||||
|
child: buildMaterial(
|
||||||
|
color: baseColor,
|
||||||
|
surfaceTintColor: surfaceTintColor,
|
||||||
|
elevation: 12.0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
final RenderPhysicalShape tintModel = getModel(tester);
|
||||||
|
|
||||||
|
// Final color should be the base with a tint of 0.14 opacity or 0xff192c33
|
||||||
|
expect(tintModel.color, equals(const Color(0xff192c33)));
|
||||||
|
});
|
||||||
|
|
||||||
|
}); // Surface Tint Overlay group
|
||||||
|
|
||||||
|
group('Elevation Overlay M2', () {
|
||||||
|
// These tests only apply to the Material 2 overlay mechanism. This group
|
||||||
|
// can be removed after migration to Material 3 is complete.
|
||||||
testWidgets('applyElevationOverlayColor set to false does not change surface color', (WidgetTester tester) async {
|
testWidgets('applyElevationOverlayColor set to false does not change surface color', (WidgetTester tester) async {
|
||||||
const Color surfaceColor = Color(0xFF121212);
|
const Color surfaceColor = Color(0xFF121212);
|
||||||
await tester.pumpWidget(Theme(
|
await tester.pumpWidget(Theme(
|
||||||
data: ThemeData(
|
data: ThemeData(
|
||||||
|
useMaterial3: false,
|
||||||
applyElevationOverlayColor: false,
|
applyElevationOverlayColor: false,
|
||||||
colorScheme: const ColorScheme.dark().copyWith(surface: surfaceColor),
|
colorScheme: const ColorScheme.dark().copyWith(surface: surfaceColor),
|
||||||
),
|
),
|
||||||
@ -303,6 +367,7 @@ void main() {
|
|||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
Theme(
|
Theme(
|
||||||
data: ThemeData(
|
data: ThemeData(
|
||||||
|
useMaterial3: false,
|
||||||
applyElevationOverlayColor: true,
|
applyElevationOverlayColor: true,
|
||||||
colorScheme: const ColorScheme.dark().copyWith(
|
colorScheme: const ColorScheme.dark().copyWith(
|
||||||
surface: surfaceColor,
|
surface: surfaceColor,
|
||||||
@ -325,6 +390,7 @@ void main() {
|
|||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
Theme(
|
Theme(
|
||||||
data: ThemeData(
|
data: ThemeData(
|
||||||
|
useMaterial3: false,
|
||||||
applyElevationOverlayColor: true,
|
applyElevationOverlayColor: true,
|
||||||
colorScheme: const ColorScheme.dark(),
|
colorScheme: const ColorScheme.dark(),
|
||||||
),
|
),
|
||||||
@ -343,6 +409,7 @@ void main() {
|
|||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
Theme(
|
Theme(
|
||||||
data: ThemeData(
|
data: ThemeData(
|
||||||
|
useMaterial3: false,
|
||||||
applyElevationOverlayColor: true,
|
applyElevationOverlayColor: true,
|
||||||
colorScheme: const ColorScheme.light(),
|
colorScheme: const ColorScheme.light(),
|
||||||
),
|
),
|
||||||
@ -364,6 +431,7 @@ void main() {
|
|||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
Theme(
|
Theme(
|
||||||
data: ThemeData(
|
data: ThemeData(
|
||||||
|
useMaterial3: false,
|
||||||
applyElevationOverlayColor: true,
|
applyElevationOverlayColor: true,
|
||||||
colorScheme: const ColorScheme.dark(),
|
colorScheme: const ColorScheme.dark(),
|
||||||
),
|
),
|
||||||
@ -390,6 +458,7 @@ void main() {
|
|||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
Theme(
|
Theme(
|
||||||
data: ThemeData(
|
data: ThemeData(
|
||||||
|
useMaterial3: false,
|
||||||
applyElevationOverlayColor: true,
|
applyElevationOverlayColor: true,
|
||||||
colorScheme: const ColorScheme.dark(
|
colorScheme: const ColorScheme.dark(
|
||||||
surface: surfaceColor,
|
surface: surfaceColor,
|
||||||
@ -407,7 +476,8 @@ void main() {
|
|||||||
expect(model.color, equals(surfaceColorWithOverlay));
|
expect(model.color, equals(surfaceColorWithOverlay));
|
||||||
expect(model.color, isNot(equals(surfaceColor)));
|
expect(model.color, isNot(equals(surfaceColor)));
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
}); // Elevation Overlay M2 group
|
||||||
|
|
||||||
group('Transparency clipping', () {
|
group('Transparency clipping', () {
|
||||||
testWidgets('No clip by default', (WidgetTester tester) async {
|
testWidgets('No clip by default', (WidgetTester tester) async {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user