[Material] Add method to get dark mode overlay color without needing BuildContext (#70669)
diff --git a/packages/flutter/lib/src/material/elevation_overlay.dart b/packages/flutter/lib/src/material/elevation_overlay.dart index cc699c6..cc5f20f 100644 --- a/packages/flutter/lib/src/material/elevation_overlay.dart +++ b/packages/flutter/lib/src/material/elevation_overlay.dart
@@ -48,7 +48,7 @@ theme.applyElevationOverlayColor && theme.brightness == Brightness.dark && color.withOpacity(1.0) == theme.colorScheme.surface.withOpacity(1.0)) { - return Color.alphaBlend(overlayColor(context, elevation), color); + return colorWithOverlay(color, theme.colorScheme.onSurface, elevation); } return color; } @@ -62,10 +62,26 @@ /// specifies the exact overlay values for a given elevation. static Color overlayColor(BuildContext context, double elevation) { final ThemeData theme = Theme.of(context); + return _overlayColor(theme.colorScheme.onSurface, elevation); + } + + /// Returns a color blended by laying a semi-transparent overlay (using the + /// [overlay] color) on top of a surface (using the [surface] color). + /// + /// The opacity of the overlay depends on [elevation]. As [elevation] + /// increases, the opacity will also increase. + /// + /// See https://material.io/design/color/dark-theme.html#properties. + static Color colorWithOverlay(Color surface, Color overlay, double elevation) { + return Color.alphaBlend(_overlayColor(overlay, elevation), surface); + } + + /// Applies an opacity to [color] based on [elevation]. + static Color _overlayColor(Color color, double elevation) { // Compute the opacity for the given elevation // This formula matches the values in the spec: // https://material.io/design/color/dark-theme.html#properties final double opacity = (4.5 * math.log(elevation + 1) + 2) / 100.0; - return theme.colorScheme.onSurface.withOpacity(opacity); + return color.withOpacity(opacity); } }
diff --git a/packages/flutter/test/material/material_test.dart b/packages/flutter/test/material/material_test.dart index 1e13244..33c91a7 100644 --- a/packages/flutter/test/material/material_test.dart +++ b/packages/flutter/test/material/material_test.dart
@@ -362,6 +362,35 @@ expect(model.color, equals(surfaceColorWithOverlay)); expect(model.color, isNot(equals(surfaceColor))); }); + + testWidgets('Expected overlay color can be computed using colorWithOverlay', (WidgetTester tester) async { + const Color surfaceColor = Color(0xFF123456); + const Color onSurfaceColor = Color(0xFF654321); + const double elevation = 8.0; + + final Color surfaceColorWithOverlay = + ElevationOverlay.colorWithOverlay(surfaceColor, onSurfaceColor, elevation); + + await tester.pumpWidget( + Theme( + data: ThemeData( + applyElevationOverlayColor: true, + colorScheme: const ColorScheme.dark( + surface: surfaceColor, + onSurface: onSurfaceColor, + ), + ), + child: buildMaterial( + color: surfaceColor, + elevation: elevation, + ), + ), + ); + + final RenderPhysicalShape model = getModel(tester); + expect(model.color, equals(surfaceColorWithOverlay)); + expect(model.color, isNot(equals(surfaceColor))); + }); }); group('Transparency clipping', () {