segmentedButtonTheme static method
SegmentedButtonThemeData
segmentedButtonTheme({
- required ColorScheme colorScheme,
- SchemeColor? selectedSchemeColor,
- SchemeColor? unselectedSchemeColor,
- SchemeColor? unselectedForegroundSchemeColor,
- SchemeColor? borderSchemeColor,
- double? radius,
- double? borderWidth,
- EdgeInsetsGeometry? padding,
- Size? minButtonSize,
- bool? useTintedInteraction,
- bool? useTintedDisable,
- InteractiveInkFeatureFactory? splashFactory,
- MaterialStateProperty<
TextStyle?> ? textStyle, - bool? useMaterial3,
An opinionated SearchBarThemeData theme for the SearchBar. An opinionated SearchViewThemeData theme for the SearchBar. An opinionated SegmentedButtonThemeData theme for the SegmentedButton.
Implementation
// static SearchBarThemeData searchBarThemeData() {
// return const SearchBarThemeData();
// }
// TODO(rydmike): Add SearchViewThemeData support.
/// An opinionated [SearchViewThemeData] theme for the [SearchBar].
// static SearchViewThemeData searchViewThemeData() {
// return const SearchViewThemeData();
// }
/// An opinionated [SegmentedButtonThemeData] theme for the [SegmentedButton].
static SegmentedButtonThemeData segmentedButtonTheme({
/// Typically the same [ColorScheme] that is also use for your [ThemeData].
required final ColorScheme colorScheme,
/// Selects which color from the passed in colorScheme to use as background
/// color for the selected button.
///
/// Defines the background color for selected button, and
/// it's onColor pair defines the foreground for selected button.
///
/// If not defined, [SchemeColor.secondaryContainer] will be used.
final SchemeColor? selectedSchemeColor,
/// Selects which color from the passed in colorScheme to use as the
/// background color for unselected segmented button.
///
/// If not defined, [SchemeColor.surface] will be used.
final SchemeColor? unselectedSchemeColor,
/// Selects which color from the passed in colorScheme to use as the
/// foreground color for unselected segmented button.
///
/// If not defined, [SchemeColor.onSurface] will be used.
final SchemeColor? unselectedForegroundSchemeColor,
/// Selects which color from the passed in colorScheme to use as the border
/// color for the toggle buttons.
///
/// If not defined, [ColorScheme.outline] will be the effective result.
final SchemeColor? borderSchemeColor,
/// The button corner radius.
///
/// If not defined, defaults to defaults to Stadium border.
final double? radius,
/// The width of the borders around the segmented button.
///
/// If null, defaults to [kThinBorderWidth] = 1.0.
final double? borderWidth,
/// Padding for the individual segment buttons.
///
/// Defaults to null and uses M3's default scaled padding function.
final EdgeInsetsGeometry? padding,
/// Minimum button size.
///
/// If null, defaults to [kButtonMinSize] (`const Size(40.0, 40.0)`) when
/// [useMaterial3] is false and to `const Size(64.0, 40.0)` when
/// [useMaterial3] is true, via M3 built in defaults.
final Size? minButtonSize,
/// 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,
/// Creates the [InkWell] splash factory, which defines the appearance of
/// "ink" splashes that occur in response to taps.
///
/// In M2 mode FlexColorScheme passes in the effective splashFactory
/// from splashFactory override value or the result from
/// [FlexSubThemesData] adaptive splash settings. In M3 mode it is kept
/// null and the default comes via ThemeData.splashFactory, that is has
/// also defined.
final InteractiveInkFeatureFactory? splashFactory,
/// The style for the segmented button's [Text] widget descendants.
///
/// The color of the [textStyle] is typically not used directly, the
/// [selectedSchemeColor] and [unselectedForegroundSchemeColor] are
/// used instead.
final MaterialStateProperty<TextStyle?>? textStyle,
/// 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;
final bool tintInteract = useTintedInteraction ?? false;
final bool tintDisable = useTintedDisable ?? false;
// We are using a light colorScheme.
final bool isLight = colorScheme.brightness == Brightness.light;
// Get selected background color, defaults to secondaryContainer.
final SchemeColor selectedScheme = selectedSchemeColor ??
(useM3 ? SchemeColor.secondaryContainer : SchemeColor.primary);
final Color selectedColor = schemeColor(selectedScheme, colorScheme);
final Color onSelectedColor = schemeColorPair(selectedScheme, colorScheme);
final Color unselectedColor =
schemeColor(unselectedSchemeColor ?? SchemeColor.surface, colorScheme);
final Color onUnselectedColor = schemeColor(
unselectedForegroundSchemeColor ??
onSchemeColor(unselectedSchemeColor ?? SchemeColor.surface),
colorScheme);
// Using these tinted overlay variable in all themes for ease of
// reasoning and duplication.
final Color overlay = onSelectedColor;
final Color tint = selectedColor;
// Get brightness of selectedColor color.
final bool selectedBgIsLight =
ThemeData.estimateBrightnessForColor(selectedColor) == Brightness.light;
// We use surface mode tint factor, if it is light theme and selectedColor
// is light OR if it is a dark theme and background is dark.
final bool selectedSurfaceMode =
(isLight && selectedBgIsLight) || (!isLight && !selectedBgIsLight);
final double factor =
_tintAlphaFactor(tint, colorScheme.brightness, selectedSurfaceMode);
final Color unOverlay = unselectedColor;
final Color unTint = unselectedSchemeColor == null ||
unselectedSchemeColor == SchemeColor.surface
? selectedColor
: onUnselectedColor;
// Get brightness of unselectedColor color.
final bool unSelectedBgIsLight =
ThemeData.estimateBrightnessForColor(unselectedColor) ==
Brightness.light;
// We use surface mode tint factor, if it is light theme and unselectedColor
// is light OR if it is a dark theme and background is dark.
final bool unSelectedSurfaceMode =
(isLight && unSelectedBgIsLight) || (!isLight && !unSelectedBgIsLight);
final double unFactor =
_tintAlphaFactor(unTint, colorScheme.brightness, unSelectedSurfaceMode);
final Color disableTint = unselectedSchemeColor == null ||
unselectedSchemeColor == SchemeColor.surface
? selectedColor
: onUnselectedColor;
final Color borderColor = schemeColor(
borderSchemeColor ??
(useM3 ? SchemeColor.outline : SchemeColor.primary),
colorScheme);
// Effective border width.
final double effectiveWidth = borderWidth ?? kThinBorderWidth;
final Color disableBorderTint = (borderSchemeColor == null && useM3) ||
unselectedSchemeColor == SchemeColor.outline
? selectedColor
: borderColor;
final Color disabledForeground = unselectedSchemeColor == null
? colorScheme.onSurface
: onUnselectedColor;
return SegmentedButtonThemeData(
style: ButtonStyle(
textStyle: textStyle,
splashFactory: splashFactory,
// TODO(rydmike): Issue, minimumSize property does nothing.
// https://github.com/flutter/flutter/issues/121493
minimumSize: ButtonStyleButton.allOrNull<Size>(
minButtonSize ?? (useM3 ? null : kButtonMinSize)),
padding: ButtonStyleButton.allOrNull<EdgeInsetsGeometry>(padding),
backgroundColor:
MaterialStateProperty.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.disabled)) {
return unselectedSchemeColor == null ? null : unselectedColor;
}
if (states.contains(MaterialState.selected)) {
return selectedColor;
}
return unselectedSchemeColor == null ? null : unselectedColor;
}),
foregroundColor:
MaterialStateProperty.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.disabled)) {
if (tintDisable) {
return tintedDisable(disabledForeground, disableTint);
}
return disabledForeground.withAlpha(kAlphaDisabled);
}
if (states.contains(MaterialState.selected)) {
if (states.contains(MaterialState.pressed)) {
return onSelectedColor;
}
if (states.contains(MaterialState.hovered)) {
return onSelectedColor;
}
if (states.contains(MaterialState.focused)) {
return onSelectedColor;
}
return onSelectedColor;
} else {
return onUnselectedColor;
}
}),
// TODO(Rydmike): Issue: Flutter SDK SegmentedButton overlayColor bug.
// https://github.com/flutter/flutter/issues/123308
// SegmentedButton triggers overlay 3 times in Selected mode, 1st
// time it is selected, next time it is no longer selected,
// even it if actually is. This results is that we never see the
// selected overlay state. It is also triggered 3 times when not
// selected, but there we get the unselected mode all times, so
// it is not noticed, still one call would be enough.
overlayColor:
MaterialStateProperty.resolveWith((Set<MaterialState> states) {
// This nicer overlay for selected overlay never gets seen due
// to above mentioned Flutter SDK bug. But if it is ever fixed it
// will get used automatically, via code below.
if (states.contains(MaterialState.selected)) {
if (states.contains(MaterialState.hovered)) {
if (tintInteract) return tintedHovered(overlay, tint, factor);
return unselectedColor.withAlpha(kAlphaHovered);
}
if (states.contains(MaterialState.focused)) {
if (tintInteract) return tintedFocused(overlay, tint, factor);
return unselectedColor.withAlpha(kAlphaFocused);
}
if (states.contains(MaterialState.pressed)) {
if (tintInteract) return tintedPressed(overlay, tint, factor);
return unselectedColor.withAlpha(kAlphaPressed);
}
} else {
if (states.contains(MaterialState.hovered)) {
if (tintInteract) {
return tintedHovered(unOverlay, unTint, unFactor);
}
return unselectedSchemeColor == null
? colorScheme.onSurface.withAlpha(kAlphaHovered)
: onUnselectedColor.withAlpha(kAlphaHovered);
}
if (states.contains(MaterialState.focused)) {
if (tintInteract) {
return tintedFocused(unOverlay, unTint, unFactor);
}
return unselectedSchemeColor == null
? colorScheme.onSurface.withAlpha(kAlphaFocused)
: onUnselectedColor.withAlpha(kAlphaFocused);
}
if (states.contains(MaterialState.pressed)) {
if (tintInteract) {
return tintedPressed(unOverlay, unTint, unFactor);
}
return unselectedSchemeColor == null
? colorScheme.onSurface.withAlpha(kAlphaPressed)
: onUnselectedColor.withAlpha(kAlphaPressed);
}
}
return null;
}),
side: MaterialStateProperty.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.disabled)) {
if (tintDisable) {
return BorderSide(
color: tintedDisable(colorScheme.onSurface, disableBorderTint)
.withAlpha(kAlphaLowDisabled),
width: effectiveWidth,
);
}
return BorderSide(
color: colorScheme.onSurface.withAlpha(kAlphaVeryLowDisabled),
width: effectiveWidth,
);
}
return BorderSide(
color: borderColor,
width: effectiveWidth,
);
}),
shape: radius == null
? null
: ButtonStyleButton.allOrNull<OutlinedBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(radius),
),
),
),
),
);
}