Unverified Commit 3a226df6 authored by Darren Austin's avatar Darren Austin Committed by GitHub

Expose the ElevationOverlay functions so applications can use the directly. (#60059)

parent 868c4d8c
...@@ -57,6 +57,7 @@ export 'src/material/divider_theme.dart'; ...@@ -57,6 +57,7 @@ export 'src/material/divider_theme.dart';
export 'src/material/drawer.dart'; export 'src/material/drawer.dart';
export 'src/material/drawer_header.dart'; export 'src/material/drawer_header.dart';
export 'src/material/dropdown.dart'; export 'src/material/dropdown.dart';
export 'src/material/elevation_overlay.dart';
export 'src/material/expand_icon.dart'; export 'src/material/expand_icon.dart';
export 'src/material/expansion_panel.dart'; export 'src/material/expansion_panel.dart';
export 'src/material/expansion_tile.dart'; export 'src/material/expansion_tile.dart';
......
...@@ -10,25 +10,29 @@ import 'package:flutter/widgets.dart'; ...@@ -10,25 +10,29 @@ import 'package:flutter/widgets.dart';
import 'theme.dart'; import 'theme.dart';
/// A simple utility class for dealing with the overlay color needed /// A utility class for dealing with the overlay color needed
/// to indicate elevation for dark theme widgets. /// to indicate elevation of surfaces in a dark theme.
///
/// This is an internal implementation class and should not be exported by
/// the material package.
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.
// ignore: unused_element // ignore: unused_element
ElevationOverlay._(); ElevationOverlay._();
/// Applies an elevation overlay color to a given color to indicate /// Applies an overlay color to a surface color to indicate
/// the level of elevation in a dark theme. /// the level of its elevation in a dark theme.
/// ///
/// If the ambient [ThemeData.applyElevationOverlayColor] is true, /// Material drop shadows can be difficult to see in a dark theme, so the
/// and [ThemeData.brightness] is [Brightness.dark] then this will return /// elevation of a surface should be portrayed with an "overlay" in addition
/// a version of the given color with a semi-transparent /// to the shadow. As the elevation of the component increases, the
/// [ThemeData.colorScheme.onSurface] overlaid on top of it. The opacity /// overlay increases in opacity. This function computes and applies this
/// of the overlay is computed based on the [elevation]. /// overlay to a given color as needed.
///
/// If the ambient theme is dark ([ThemeData.brightness] is [Brightness.dark]),
/// and [ThemeData.applyElevationOverlayColor] is true, and the given
/// [color] is [ColorScheme.surface] then this will return a version of
/// the [color] with a semi-transparent [ColorScheme.onSurface] overlaid
/// on top of it. The opacity of the overlay is computed based on the
/// [elevation].
/// ///
/// Otherwise it will just return the [color] unmodified. /// Otherwise it will just return the [color] unmodified.
/// ///
...@@ -37,12 +41,15 @@ class ElevationOverlay { ...@@ -37,12 +41,15 @@ class ElevationOverlay {
/// * [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.
/// * [overlayColor] which computes the needed overlay color. /// * [overlayColor] which computes the needed overlay color.
/// * [Material] which uses this to apply an elevation overlay to its surface.
/// * <https://material.io/design/color/dark-theme.html>, which specifies how
/// the overlay should be applied.
static Color applyOverlay(BuildContext context, Color color, double elevation) { static Color applyOverlay(BuildContext context, Color color, double elevation) {
final ThemeData theme = Theme.of(context); final ThemeData theme = Theme.of(context);
if (elevation > 0.0 && if (elevation > 0.0 &&
theme.applyElevationOverlayColor && theme.applyElevationOverlayColor &&
theme.brightness == Brightness.dark) { theme.brightness == Brightness.dark &&
color == theme.colorScheme.surface) {
return Color.alphaBlend(overlayColor(context, elevation), color); return Color.alphaBlend(overlayColor(context, elevation), color);
} }
return color; return color;
......
...@@ -945,15 +945,13 @@ class ThemeData with Diagnosticable { ...@@ -945,15 +945,13 @@ class ThemeData with Diagnosticable {
/// ///
/// If [true] and [brightness] is [Brightness.dark], a /// If [true] and [brightness] is [Brightness.dark], a
/// semi-transparent version of [colorScheme.onSurface] will be /// semi-transparent version of [colorScheme.onSurface] will be
/// applied on top of the color of [Material] widgets. The level of /// applied on top of [Material] widgets that have a [colorScheme.surface]
/// transparency is based on [Material.elevation] as per the /// color. The level of transparency is based on [Material.elevation] as
/// Material Dark theme specification. /// per the Material Dark theme specification.
/// ///
/// If [false] the surface color will be used unmodified. /// If [false] the surface color will be used unmodified.
/// ///
/// Defaults to [false]. /// Defaults to [false] in order to maintain backwards compatibility with
///
/// Note: this setting is here to maintain backwards compatibility with
/// apps that were built before the Material Dark theme specification /// apps that were built before the Material Dark theme specification
/// was published. New apps should set this to [true] for any themes /// was published. New apps should set this to [true] for any themes
/// where [brightness] is [Brightness.dark]. /// where [brightness] is [Brightness.dark].
...@@ -962,7 +960,8 @@ class ThemeData with Diagnosticable { ...@@ -962,7 +960,8 @@ class ThemeData with Diagnosticable {
/// ///
/// * [Material.elevation], which effects the level of transparency of the /// * [Material.elevation], which effects the level of transparency of the
/// overlay color. /// overlay color.
/// * [Material.color], the elevation overlay will be applied to this color. /// * [ElevationOverlay.applyOverlay], which is used by [Material] to apply
/// the overlay color to its surface color.
/// * <https://material.io/design/color/dark-theme.html>, which specifies how /// * <https://material.io/design/color/dark-theme.html>, which specifies how
/// the overlay should be applied. /// the overlay should be applied.
final bool applyElevationOverlayColor; final bool applyElevationOverlayColor;
......
...@@ -275,6 +275,24 @@ void main() { ...@@ -275,6 +275,24 @@ void main() {
} }
}); });
testWidgets('overlay will not apply to materials using a non-surface color', (WidgetTester tester) async {
await tester.pumpWidget(
Theme(
data: ThemeData(
applyElevationOverlayColor: true,
colorScheme: const ColorScheme.dark(),
),
child: buildMaterial(
color: Colors.cyan,
elevation: 8.0,
),
),
);
final RenderPhysicalShape model = getModel(tester);
// Shouldn't change, as it is not using a ColorScheme.surface color
expect(model.color, equals(Colors.cyan));
});
testWidgets('overlay will not apply to materials using a light theme', (WidgetTester tester) async { testWidgets('overlay will not apply to materials using a light theme', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
Theme( Theme(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment