elevation_overlay.dart 2.96 KB
Newer Older
Ian Hickson's avatar
Ian Hickson committed
1
// Copyright 2014 The Flutter Authors. All rights reserved.
2 3
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
Ian Hickson's avatar
Ian Hickson committed
4

5 6
// @dart = 2.8

7 8 9 10 11 12
import 'dart:math' as math;

import 'package:flutter/widgets.dart';

import 'theme.dart';

13 14
/// A utility class for dealing with the overlay color needed
/// to indicate elevation of surfaces in a dark theme.
15
class ElevationOverlay {
16
  // This class is not meant to be instantiated or extended; this constructor
17 18
  // prevents instantiation and extension.
  // ignore: unused_element
19 20
  ElevationOverlay._();

21 22
  /// Applies an overlay color to a surface color to indicate
  /// the level of its elevation in a dark theme.
23
  ///
24 25 26 27 28 29 30 31 32 33 34 35
  /// 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
  /// to the shadow. As the elevation of the component increases, the
  /// overlay increases in opacity. This function computes and applies this
  /// 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].
36 37 38 39 40
  ///
  /// Otherwise it will just return the [color] unmodified.
  ///
  /// See also:
  ///
41 42 43
  ///  * [ThemeData.applyElevationOverlayColor] which controls the whether
  ///    an overlay color will be applied to indicate elevation.
  ///  * [overlayColor] which computes the needed overlay color.
44 45 46
  ///  * [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.
47 48 49 50
  static Color applyOverlay(BuildContext context, Color color, double elevation) {
    final ThemeData theme = Theme.of(context);
    if (elevation > 0.0 &&
        theme.applyElevationOverlayColor &&
51 52
        theme.brightness == Brightness.dark &&
        color == theme.colorScheme.surface) {
53 54 55 56 57 58 59 60 61 62
      return Color.alphaBlend(overlayColor(context, elevation), color);
    }
    return color;
  }

  /// Computes the appropriate overlay color used to indicate elevation in
  /// dark themes.
  ///
  /// See also:
  ///
63 64
  ///  * https://material.io/design/color/dark-theme.html#properties which
  ///    specifies the exact overlay values for a given elevation.
65 66 67 68 69 70 71 72 73
  static Color overlayColor(BuildContext context, double elevation) {
    final ThemeData theme = Theme.of(context);
    // 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);
  }
}