switchTheme static method

SwitchThemeData switchTheme({
  1. required ColorScheme colorScheme,
  2. SchemeColor? baseSchemeColor,
  3. SchemeColor? thumbSchemeColor,
  4. bool? thumbFixedSize,
  5. double? splashRadius,
  6. bool? unselectedIsColored,
  7. bool? useTintedInteraction,
  8. bool? useTintedDisable,
  9. bool? useMaterial3,
})

An opinionated SwitchThemeData theme.

Requires a ColorScheme in colorscheme. The color scheme would typically be equal the color scheme also used to define the color scheme for your app theme.

The splashRadius is not used by FlexColorScheme sub-themes.

Implementation

static SwitchThemeData switchTheme({
  /// Typically the same `ColorScheme` that is also used for your `ThemeData`.
  required final ColorScheme colorScheme,

  /// Selects which color from the passed in colorScheme to use as the main
  /// color for the switch.
  ///
  /// All colors in the color scheme are not good choices, but some work well.
  ///
  /// If not defined, [colorScheme.primary] will be used. This is more in-line
  /// with M3 design, but applied to M2 switch. The M3 color design
  /// specification for the secondary color, is a poor choice for toggles and
  /// switches, if such colors are used in M2 mode, primary color works
  /// better.
  final SchemeColor? baseSchemeColor,

  /// Selects which color from the passed in colorScheme to use as the thumb
  /// color for the switch.
  ///
  /// All colors in the color scheme are not good choices, but some work well.
  ///
  /// If not defined, [colorScheme.primary] will be used in M2 mode.
  /// This is more in-line
  /// with M3 design, but applied to M2 switch. The M3 color design
  /// specification for the secondary color, is a poor choice for toggles and
  /// switches, if such colors are used in M2 mode, primary color works
  /// better.
  ///
  /// If not defined, defaults to:
  ///
  /// - If useMaterial3 is false [baseSchemeColor].
  /// - If useMaterial3 is true [SchemeColor.primaryContainer].
  final SchemeColor? thumbSchemeColor,

  /// Set to true to keep the [Switch] thumb size fixed.
  ///
  /// When true the [Switch] thumb size does not change from small size when
  /// OFF, to a larger size when ON. This makes the Material-3 Switch even
  /// more similar to the iOS style Switch.
  ///
  /// This setting only applies to the Material-3 mode, it has no effect in
  /// Material-2 mode.
  ///
  /// If undefined, defaults to false.
  final bool? thumbFixedSize,

  /// The splash radius of the circular Material ink response.
  ///
  /// If null, default via SDK defaults to [kRadialReactionRadius] = 20.
  final double? splashRadius,

  /// Defines if unselected [Switch] is also themed to be [baseSchemeColor].
  ///
  /// If false, it is grey like in Flutter SDK.
  ///
  /// If undefined, defaults to false.
  final bool? unselectedIsColored,

  /// Defines if the theme uses tinted interaction effects.
  ///
  /// If undefined, defaults to false.
  final bool? useTintedInteraction,

  /// Defines if the theme uses tinted disabled color.
  ///
  /// If undefined, defaults to false.
  final bool? useTintedDisable,

  /// A temporary flag used to opt-in to Material 3 features.
  ///
  /// If set to true, the theme will use Material3 default styles when
  /// properties are undefined, if false defaults will use FlexColorScheme's
  /// own opinionated default values.
  ///
  /// The M2/M3 defaults will only be used for properties that are not
  /// defined, if defined they keep their defined values.
  ///
  /// If undefined, defaults to false.
  final bool? useMaterial3,
}) {
  final bool useM3 = useMaterial3 ?? false;

  // Get colorScheme brightness.
  final bool isLight = colorScheme.brightness == Brightness.light;
  // Get selected base color, and its pair, defaults to primary and onPrimary.
  final Color baseColor =
      schemeColor(baseSchemeColor ?? SchemeColor.primary, colorScheme);

  final Color onBaseColor =
      schemeColorPair(baseSchemeColor ?? SchemeColor.primary, colorScheme);

  final bool unselectedColored = unselectedIsColored ?? false;
  final bool tintInteract = useTintedInteraction ?? false;
  final bool tintDisable = useTintedDisable ?? false;

  // Using these tinted overlay variable in all themes for ease of
  // reasoning and duplication.
  final Color overlay = colorScheme.surface;
  final Color tint = baseColor;
  final double factor = _tintAlphaFactor(tint, colorScheme.brightness, true);

  // Get selected thumb color, and its pair, defaults to
  // M2: primary and onPrimary.
  // M3: primaryContainer and onPrimaryContainer
  final Color thumbColor = schemeColor(
      thumbSchemeColor ??
          (useM3
              ? SchemeColor.primaryContainer
              : baseSchemeColor ?? SchemeColor.primary),
      colorScheme);

  // Material 2 style Switch
  if (!useM3) {
    return SwitchThemeData(
      splashRadius: splashRadius,
      thumbColor: MaterialStateProperty.resolveWith<Color>(
        (Set<MaterialState> states) {
          if (states.contains(MaterialState.disabled)) {
            if (states.contains(MaterialState.selected)) {
              if (tintDisable) {
                return tintedDisable(colorScheme.onSurface, baseColor);
              }
              return isLight ? Colors.grey.shade400 : Colors.grey.shade800;
            }
            if (tintDisable) {
              return tintedDisable(colorScheme.onSurface, baseColor)
                  .withAlpha(kAlphaLowDisabled);
            }
            return isLight ? Colors.grey.shade400 : Colors.grey.shade800;
          }
          if (states.contains(MaterialState.selected)) {
            return thumbColor;
          }
          return isLight ? Colors.grey.shade50 : Colors.grey.shade400;
        },
      ),
      trackColor: MaterialStateProperty.resolveWith<Color>(
        (Set<MaterialState> states) {
          if (states.contains(MaterialState.disabled)) {
            if (tintDisable) {
              return tintedDisable(colorScheme.onSurface, baseColor)
                  .withAlpha(kAlphaVeryLowDisabled);
            }
            return isLight ? Colors.black12 : Colors.white10;
          }
          if (states.contains(MaterialState.selected)) {
            return baseColor.withAlpha(
                isLight ? kAlphaM2SwitchTrackLight : kAlphaM2SwitchTrackDark);
          }
          // Custom themed color on track when not selected
          if (unselectedColored) {
            return baseColor.withAlpha(isLight
                ? kAlphaM2SwitchUnselectTrackLight
                : kAlphaM2SwitchUnselectTrackDark);
          }
          // This is SDK default, yes that value is hard coded in SDK too.
          return isLight ? kSwitchM2LightTrackColor : Colors.white30;
        },
      ),
      overlayColor:
          MaterialStateProperty.resolveWith((Set<MaterialState> states) {
        if (states.contains(MaterialState.selected)) {
          if (states.contains(MaterialState.pressed)) {
            if (tintInteract) return tintedPressed(overlay, tint, factor);
            return baseColor.withAlpha(kAlphaPressed);
          }
          if (states.contains(MaterialState.hovered)) {
            if (tintInteract) return tintedHovered(overlay, tint, factor);
            return baseColor.withAlpha(kAlphaHovered);
          }
          if (states.contains(MaterialState.focused)) {
            if (tintInteract) return tintedFocused(overlay, tint, factor);
            return baseColor.withAlpha(kAlphaFocused);
          }
          return null;
        }
        if (states.contains(MaterialState.pressed)) {
          if (tintInteract) return tintedPressed(overlay, tint, factor);
          return colorScheme.onSurface.withAlpha(kAlphaPressed);
        }
        if (states.contains(MaterialState.hovered)) {
          if (tintInteract) return tintedHovered(overlay, tint, factor);
          return colorScheme.onSurface.withAlpha(kAlphaHovered);
        }
        if (states.contains(MaterialState.focused)) {
          if (tintInteract) return tintedFocused(overlay, tint, factor);
          return colorScheme.onSurface.withAlpha(kAlphaFocused);
        }
        return null;
      }),
    );
  }
  // Material 3 style Switch
  else {
    return SwitchThemeData(
      splashRadius: splashRadius,
      thumbIcon: thumbFixedSize ?? false
          ? MaterialStateProperty.resolveWith<Icon?>(
              (Set<MaterialState> states) {
              return const Icon(Icons.minimize, color: Colors.transparent);
            })
          : null,
      thumbColor:
          MaterialStateProperty.resolveWith((Set<MaterialState> states) {
        if (states.contains(MaterialState.disabled)) {
          if (states.contains(MaterialState.selected)) {
            return colorScheme.surface;
          }
          if (tintDisable) {
            return tintedDisable(colorScheme.onSurface, baseColor);
          }
          return colorScheme.onSurface.withAlpha(kAlphaDisabled);
        }
        if (states.contains(MaterialState.selected)) {
          if (states.contains(MaterialState.pressed)) {
            return thumbColor;
          }
          if (states.contains(MaterialState.hovered)) {
            return thumbColor;
          }
          if (states.contains(MaterialState.focused)) {
            return thumbColor;
          }
          return onBaseColor;
        }
        if (states.contains(MaterialState.pressed)) {
          return colorScheme.onSurfaceVariant;
        }
        if (states.contains(MaterialState.hovered)) {
          return colorScheme.onSurfaceVariant;
        }
        if (states.contains(MaterialState.focused)) {
          return colorScheme.onSurfaceVariant;
        }
        return colorScheme.outline;
      }),
      trackColor:
          MaterialStateProperty.resolveWith((Set<MaterialState> states) {
        if (states.contains(MaterialState.disabled)) {
          if (states.contains(MaterialState.selected)) {
            if (tintDisable) {
              return tintedDisable(colorScheme.onSurface, baseColor);
            }
            return colorScheme.onSurface.withAlpha(kAlphaVeryLowDisabled);
          }
          return colorScheme.surfaceVariant.withAlpha(kAlphaVeryLowDisabled);
        }
        if (states.contains(MaterialState.selected)) {
          if (states.contains(MaterialState.pressed)) {
            return baseColor;
          }
          if (states.contains(MaterialState.hovered)) {
            return baseColor;
          }
          if (states.contains(MaterialState.focused)) {
            return baseColor;
          }
          return baseColor;
        }
        if (states.contains(MaterialState.pressed)) {
          return unselectedColored
              ? baseColor.withAlpha(isLight
                  ? kAlphaM3SwitchUnselectTrackLight
                  : kAlphaM3SwitchUnselectTrackDark)
              : colorScheme.surfaceVariant;
        }
        if (states.contains(MaterialState.hovered)) {
          return unselectedColored
              ? baseColor.withAlpha(isLight
                  ? kAlphaM3SwitchUnselectTrackLight
                  : kAlphaM3SwitchUnselectTrackDark)
              : colorScheme.surfaceVariant;
        }
        if (states.contains(MaterialState.focused)) {
          return unselectedColored
              ? baseColor.withAlpha(isLight
                  ? kAlphaM3SwitchUnselectTrackLight
                  : kAlphaM3SwitchUnselectTrackDark)
              : colorScheme.surfaceVariant;
        }
        return unselectedColored
            ? baseColor.withAlpha(isLight
                ? kAlphaM3SwitchUnselectTrackLight
                : kAlphaM3SwitchUnselectTrackDark)
            : colorScheme.surfaceVariant;
      }),
      trackOutlineColor:
          MaterialStateProperty.resolveWith((Set<MaterialState> states) {
        if (states.contains(MaterialState.selected)) {
          return Colors.transparent;
        }
        if (states.contains(MaterialState.disabled)) {
          if (tintDisable) {
            return tintedDisable(colorScheme.onSurface, baseColor);
          }
          return colorScheme.onSurface.withAlpha(kAlphaVeryLowDisabled);
        }
        return colorScheme.outline;
      }),
      overlayColor:
          MaterialStateProperty.resolveWith((Set<MaterialState> states) {
        if (states.contains(MaterialState.selected)) {
          if (states.contains(MaterialState.pressed)) {
            if (tintInteract) return tintedPressed(overlay, tint, factor);
            return baseColor.withAlpha(kAlphaPressed);
          }
          if (states.contains(MaterialState.hovered)) {
            if (tintInteract) return tintedHovered(overlay, tint, factor);
            return baseColor.withAlpha(kAlphaHovered);
          }
          if (states.contains(MaterialState.focused)) {
            if (tintInteract) return tintedFocused(overlay, tint, factor);
            return baseColor.withAlpha(kAlphaFocused);
          }
          return null;
        }
        if (states.contains(MaterialState.pressed)) {
          if (tintInteract) return tintedPressed(overlay, tint, factor);
          return colorScheme.onSurface.withAlpha(kAlphaPressed);
        }
        if (states.contains(MaterialState.hovered)) {
          if (tintInteract) return tintedHovered(overlay, tint, factor);
          return colorScheme.onSurface.withAlpha(kAlphaHovered);
        }
        if (states.contains(MaterialState.focused)) {
          if (tintInteract) return tintedFocused(overlay, tint, factor);
          return colorScheme.onSurface.withAlpha(kAlphaFocused);
        }
        return null;
      }),
    );
  }
}