Skip to content

Commit fa85f69

Browse files
authored
Add missing overlayColor property in styleFrom methods (#146685)
fixes [Add missing `overlayColor` property in `styleFrom` methods](flutter/flutter#146636) ### Code sample <details> <summary>expand to view the code sample</summary> ```dart import 'package:flutter/material.dart'; enum Sizes { extraSmall, small, medium, large, extraLarge } void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp({super.key}); @OverRide Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, home: Scaffold( body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: <Widget>[ Text('styleFrom(overlayColor: Colors.red)', style: Theme.of(context).textTheme.titleLarge), TextButton( style: TextButton.styleFrom(overlayColor: Colors.red), onPressed: () {}, child: const Text('TextButton'), ), IconButton( style: IconButton.styleFrom( overlayColor: Colors.red, ), onPressed: () {}, icon: const Icon(Icons.add), ), MenuBar( children: [ MenuItemButton( style: MenuItemButton.styleFrom(overlayColor: Colors.red), child: const Text('MenuItemButton'), onPressed: () {}, ), SubmenuButton( style: SubmenuButton.styleFrom(overlayColor: Colors.red), menuChildren: [ MenuItemButton( child: const Text('MenuItemButton'), onPressed: () {}, ), ], child: const Text('SubmenuButton'), ), ], ), SegmentedButton<Sizes>( style: SegmentedButton.styleFrom(overlayColor: Colors.red), segments: const <ButtonSegment<Sizes>>[ ButtonSegment<Sizes>( value: Sizes.extraSmall, label: Text('XS')), ButtonSegment<Sizes>(value: Sizes.small, label: Text('S')), ButtonSegment<Sizes>(value: Sizes.medium, label: Text('M')), ButtonSegment<Sizes>( value: Sizes.large, label: Text('L'), ), ButtonSegment<Sizes>( value: Sizes.extraLarge, label: Text('XL')), ], selected: const {Sizes.medium}, onSelectionChanged: (Set<Sizes> newSelection) {}, multiSelectionEnabled: true, ), ], ), ), ), ); } } ``` </details> ### Preview ![ScreenRecording2024-04-12at15 25 58-ezgif com-video-to-gif-converter](https://github.com/flutter/flutter/assets/48603081/89b9638d-f369-4ef1-b501-17c9c74b2541)
1 parent ffea970 commit fa85f69

9 files changed

+611
-74
lines changed

dev/tools/gen_defaults/lib/segmented_button_template.dart

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -120,27 +120,27 @@ class _${blockName}DefaultsM3 extends SegmentedButtonThemeData {
120120
@override
121121
Widget? get selectedIcon => const Icon(Icons.check);
122122
123-
static MaterialStateProperty<Color?> resolveStateColor(Color? unselectedColor, Color? selectedColor){
123+
static MaterialStateProperty<Color?> resolveStateColor(Color? unselectedColor, Color? selectedColor, Color? overlayColor){
124124
return MaterialStateProperty.resolveWith((Set<MaterialState> states) {
125125
if (states.contains(MaterialState.selected)) {
126126
if (states.contains(MaterialState.pressed)) {
127-
return selectedColor?.withOpacity(0.1);
127+
return (overlayColor ?? selectedColor)?.withOpacity(0.1);
128128
}
129129
if (states.contains(MaterialState.hovered)) {
130-
return selectedColor?.withOpacity(0.08);
130+
return (overlayColor ?? selectedColor)?.withOpacity(0.08);
131131
}
132132
if (states.contains(MaterialState.focused)) {
133-
return selectedColor?.withOpacity(0.1);
133+
return (overlayColor ?? selectedColor)?.withOpacity(0.1);
134134
}
135135
} else {
136136
if (states.contains(MaterialState.pressed)) {
137-
return unselectedColor?.withOpacity(0.1);
137+
return (overlayColor ?? unselectedColor)?.withOpacity(0.1);
138138
}
139139
if (states.contains(MaterialState.hovered)) {
140-
return unselectedColor?.withOpacity(0.08);
140+
return (overlayColor ?? unselectedColor)?.withOpacity(0.08);
141141
}
142142
if (states.contains(MaterialState.focused)) {
143-
return unselectedColor?.withOpacity(0.1);
143+
return (overlayColor ?? unselectedColor)?.withOpacity(0.1);
144144
}
145145
}
146146
return Colors.transparent;

packages/flutter/lib/src/material/icon_button.dart

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -573,9 +573,15 @@ class IconButton extends StatelessWidget {
573573
/// [ButtonStyle.foregroundColor] value. Specify a value for [foregroundColor]
574574
/// to specify the color of the button's icons. The [hoverColor], [focusColor]
575575
/// and [highlightColor] colors are used to indicate the hover, focus,
576-
/// and pressed states. Use [backgroundColor] for the button's background
577-
/// fill color. Use [disabledForegroundColor] and [disabledBackgroundColor]
578-
/// to specify the button's disabled icon and fill color.
576+
/// and pressed states if [overlayColor] isn't specified.
577+
///
578+
/// If [overlayColor] is specified and its value is [Colors.transparent]
579+
/// then the pressed/focused/hovered highlights are effectively defeated.
580+
/// Otherwise a [MaterialStateProperty] with the same opacities as the
581+
/// default is created.
582+
///
583+
/// Use [backgroundColor] for the button's background fill color. Use [disabledForegroundColor]
584+
/// and [disabledBackgroundColor] to specify the button's disabled icon and fill color.
579585
///
580586
/// Similarly, the [enabledMouseCursor] and [disabledMouseCursor]
581587
/// parameters are used to construct [ButtonStyle].mouseCursor.
@@ -611,6 +617,7 @@ class IconButton extends StatelessWidget {
611617
Color? highlightColor,
612618
Color? shadowColor,
613619
Color? surfaceTintColor,
620+
Color? overlayColor,
614621
double? elevation,
615622
Size? minimumSize,
616623
Size? fixedSize,
@@ -629,20 +636,24 @@ class IconButton extends StatelessWidget {
629636
InteractiveInkFeatureFactory? splashFactory,
630637
}) {
631638
final MaterialStateProperty<Color?>? buttonBackgroundColor = (backgroundColor == null && disabledBackgroundColor == null)
632-
? null
633-
: _IconButtonDefaultBackground(backgroundColor, disabledBackgroundColor);
639+
? null
640+
: _IconButtonDefaultBackground(backgroundColor, disabledBackgroundColor);
634641
final MaterialStateProperty<Color?>? buttonForegroundColor = (foregroundColor == null && disabledForegroundColor == null)
642+
? null
643+
: _IconButtonDefaultForeground(foregroundColor, disabledForegroundColor);
644+
final MaterialStateProperty<Color?>? overlayColorProp = (foregroundColor == null &&
645+
hoverColor == null && focusColor == null && highlightColor == null && overlayColor == null)
635646
? null
636-
: _IconButtonDefaultForeground(foregroundColor, disabledForegroundColor);
637-
final MaterialStateProperty<Color?>? overlayColor = (foregroundColor == null && hoverColor == null && focusColor == null && highlightColor == null)
638-
? null
639-
: _IconButtonDefaultOverlay(foregroundColor, focusColor, hoverColor, highlightColor);
647+
: switch (overlayColor) {
648+
(final Color overlayColor) when overlayColor.value == 0 => const MaterialStatePropertyAll<Color?>(Colors.transparent),
649+
_ => _IconButtonDefaultOverlay(foregroundColor, focusColor, hoverColor, highlightColor, overlayColor),
650+
};
640651
final MaterialStateProperty<MouseCursor?> mouseCursor = _IconButtonDefaultMouseCursor(enabledMouseCursor, disabledMouseCursor);
641652

642653
return ButtonStyle(
643654
backgroundColor: buttonBackgroundColor,
644655
foregroundColor: buttonForegroundColor,
645-
overlayColor: overlayColor,
656+
overlayColor: overlayColorProp,
646657
shadowColor: ButtonStyleButton.allOrNull<Color>(shadowColor),
647658
surfaceTintColor: ButtonStyleButton.allOrNull<Color>(surfaceTintColor),
648659
elevation: ButtonStyleButton.allOrNull<double>(elevation),
@@ -1023,34 +1034,41 @@ class _IconButtonDefaultForeground extends MaterialStateProperty<Color?> {
10231034

10241035
@immutable
10251036
class _IconButtonDefaultOverlay extends MaterialStateProperty<Color?> {
1026-
_IconButtonDefaultOverlay(this.foregroundColor, this.focusColor, this.hoverColor, this.highlightColor);
1037+
_IconButtonDefaultOverlay(
1038+
this.foregroundColor,
1039+
this.focusColor,
1040+
this.hoverColor,
1041+
this.highlightColor,
1042+
this.overlayColor,
1043+
);
10271044

10281045
final Color? foregroundColor;
10291046
final Color? focusColor;
10301047
final Color? hoverColor;
10311048
final Color? highlightColor;
1049+
final Color? overlayColor;
10321050

10331051
@override
10341052
Color? resolve(Set<MaterialState> states) {
10351053
if (states.contains(MaterialState.selected)) {
10361054
if (states.contains(MaterialState.pressed)) {
1037-
return highlightColor ?? foregroundColor?.withOpacity(0.1);
1055+
return highlightColor ?? (overlayColor ?? foregroundColor)?.withOpacity(0.1);
10381056
}
10391057
if (states.contains(MaterialState.hovered)) {
1040-
return hoverColor ?? foregroundColor?.withOpacity(0.08);
1058+
return hoverColor ?? (overlayColor ?? foregroundColor)?.withOpacity(0.08);
10411059
}
10421060
if (states.contains(MaterialState.focused)) {
1043-
return focusColor ?? foregroundColor?.withOpacity(0.1);
1061+
return focusColor ?? (overlayColor ?? foregroundColor)?.withOpacity(0.1);
10441062
}
10451063
}
10461064
if (states.contains(MaterialState.pressed)) {
1047-
return highlightColor ?? foregroundColor?.withOpacity(0.1);
1065+
return highlightColor ?? (overlayColor ?? foregroundColor)?.withOpacity(0.1);
10481066
}
10491067
if (states.contains(MaterialState.hovered)) {
1050-
return hoverColor ?? foregroundColor?.withOpacity(0.08);
1068+
return hoverColor ?? (overlayColor ?? foregroundColor)?.withOpacity(0.08);
10511069
}
10521070
if (states.contains(MaterialState.focused)) {
1053-
return focusColor ?? foregroundColor?.withOpacity(0.1);
1071+
return focusColor ?? (overlayColor ?? foregroundColor)?.withOpacity(0.1);
10541072
}
10551073
return null;
10561074
}

packages/flutter/lib/src/material/menu_anchor.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1022,6 +1022,7 @@ class MenuItemButton extends StatefulWidget {
10221022
Color? surfaceTintColor,
10231023
Color? iconColor,
10241024
TextStyle? textStyle,
1025+
Color? overlayColor,
10251026
double? elevation,
10261027
EdgeInsetsGeometry? padding,
10271028
Size? minimumSize,
@@ -1047,6 +1048,7 @@ class MenuItemButton extends StatefulWidget {
10471048
surfaceTintColor: surfaceTintColor,
10481049
iconColor: iconColor,
10491050
textStyle: textStyle,
1051+
overlayColor: overlayColor,
10501052
elevation: elevation,
10511053
padding: padding,
10521054
minimumSize: minimumSize,
@@ -1775,6 +1777,7 @@ class SubmenuButton extends StatefulWidget {
17751777
Color? surfaceTintColor,
17761778
Color? iconColor,
17771779
TextStyle? textStyle,
1780+
Color? overlayColor,
17781781
double? elevation,
17791782
EdgeInsetsGeometry? padding,
17801783
Size? minimumSize,
@@ -1800,6 +1803,7 @@ class SubmenuButton extends StatefulWidget {
18001803
surfaceTintColor: surfaceTintColor,
18011804
iconColor: iconColor,
18021805
textStyle: textStyle,
1806+
overlayColor: overlayColor,
18031807
elevation: elevation,
18041808
padding: padding,
18051809
minimumSize: minimumSize,

packages/flutter/lib/src/material/segmented_button.dart

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,12 @@ class SegmentedButton<T> extends StatefulWidget {
203203
///
204204
/// The [foregroundColor], [selectedForegroundColor], and [disabledForegroundColor]
205205
/// colors are used to create a [MaterialStateProperty] [ButtonStyle.foregroundColor],
206-
/// and a derived [ButtonStyle.overlayColor].
206+
/// and a derived [ButtonStyle.overlayColor] if [overlayColor] isn't specified.
207+
///
208+
/// If [overlayColor] is specified and its value is [Colors.transparent]
209+
/// then the pressed/focused/hovered highlights are effectively defeated.
210+
/// Otherwise a [MaterialStateProperty] with the same opacities as the
211+
/// default is created.
207212
///
208213
/// The [backgroundColor], [selectedBackgroundColor] and [disabledBackgroundColor]
209214
/// colors are used to create a [MaterialStateProperty] [ButtonStyle.backgroundColor].
@@ -261,6 +266,7 @@ class SegmentedButton<T> extends StatefulWidget {
261266
Color? disabledBackgroundColor,
262267
Color? shadowColor,
263268
Color? surfaceTintColor,
269+
Color? overlayColor,
264270
double? elevation,
265271
TextStyle? textStyle,
266272
EdgeInsetsGeometry? padding,
@@ -286,9 +292,13 @@ class SegmentedButton<T> extends StatefulWidget {
286292
(backgroundColor == null && disabledBackgroundColor == null && selectedBackgroundColor == null)
287293
? null
288294
: _SegmentButtonDefaultColor(backgroundColor, disabledBackgroundColor, selectedBackgroundColor);
289-
final MaterialStateProperty<Color?>? overlayColor = (foregroundColor == null && selectedForegroundColor == null)
290-
? null
291-
: _SegmentedButtonDefaultsM3.resolveStateColor(foregroundColor, selectedForegroundColor);
295+
final MaterialStateProperty<Color?>? overlayColorProp = (foregroundColor == null &&
296+
selectedForegroundColor == null && overlayColor == null)
297+
? null
298+
: switch (overlayColor) {
299+
(final Color overlayColor) when overlayColor.value == 0 => const MaterialStatePropertyAll<Color?>(Colors.transparent),
300+
_ => _SegmentedButtonDefaultsM3.resolveStateColor(foregroundColor, selectedForegroundColor, overlayColor),
301+
};
292302
return TextButton.styleFrom(
293303
textStyle: textStyle,
294304
shadowColor: shadowColor,
@@ -311,7 +321,7 @@ class SegmentedButton<T> extends StatefulWidget {
311321
).copyWith(
312322
foregroundColor: foregroundColorProp,
313323
backgroundColor: backgroundColorProp,
314-
overlayColor: overlayColor,
324+
overlayColor: overlayColorProp,
315325
);
316326
}
317327

@@ -1066,27 +1076,27 @@ class _SegmentedButtonDefaultsM3 extends SegmentedButtonThemeData {
10661076
@override
10671077
Widget? get selectedIcon => const Icon(Icons.check);
10681078

1069-
static MaterialStateProperty<Color?> resolveStateColor(Color? unselectedColor, Color? selectedColor){
1079+
static MaterialStateProperty<Color?> resolveStateColor(Color? unselectedColor, Color? selectedColor, Color? overlayColor){
10701080
return MaterialStateProperty.resolveWith((Set<MaterialState> states) {
10711081
if (states.contains(MaterialState.selected)) {
10721082
if (states.contains(MaterialState.pressed)) {
1073-
return selectedColor?.withOpacity(0.1);
1083+
return (overlayColor ?? selectedColor)?.withOpacity(0.1);
10741084
}
10751085
if (states.contains(MaterialState.hovered)) {
1076-
return selectedColor?.withOpacity(0.08);
1086+
return (overlayColor ?? selectedColor)?.withOpacity(0.08);
10771087
}
10781088
if (states.contains(MaterialState.focused)) {
1079-
return selectedColor?.withOpacity(0.1);
1089+
return (overlayColor ?? selectedColor)?.withOpacity(0.1);
10801090
}
10811091
} else {
10821092
if (states.contains(MaterialState.pressed)) {
1083-
return unselectedColor?.withOpacity(0.1);
1093+
return (overlayColor ?? unselectedColor)?.withOpacity(0.1);
10841094
}
10851095
if (states.contains(MaterialState.hovered)) {
1086-
return unselectedColor?.withOpacity(0.08);
1096+
return (overlayColor ?? unselectedColor)?.withOpacity(0.08);
10871097
}
10881098
if (states.contains(MaterialState.focused)) {
1089-
return unselectedColor?.withOpacity(0.1);
1099+
return (overlayColor ?? unselectedColor)?.withOpacity(0.1);
10901100
}
10911101
}
10921102
return Colors.transparent;

0 commit comments

Comments
 (0)