Skip to content

Commit

Permalink
Add missing overlayColor property in styleFrom methods (flutter#1…
Browse files Browse the repository at this point in the history
…46685)

fixes [Add missing `overlayColor` property  in `styleFrom` methods](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)
  • Loading branch information
TahaTesser authored Apr 24, 2024
1 parent ffea970 commit fa85f69
Show file tree
Hide file tree
Showing 9 changed files with 611 additions and 74 deletions.
14 changes: 7 additions & 7 deletions dev/tools/gen_defaults/lib/segmented_button_template.dart
Original file line number Diff line number Diff line change
Expand Up @@ -120,27 +120,27 @@ class _${blockName}DefaultsM3 extends SegmentedButtonThemeData {
@override
Widget? get selectedIcon => const Icon(Icons.check);
static MaterialStateProperty<Color?> resolveStateColor(Color? unselectedColor, Color? selectedColor){
static MaterialStateProperty<Color?> resolveStateColor(Color? unselectedColor, Color? selectedColor, Color? overlayColor){
return MaterialStateProperty.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.selected)) {
if (states.contains(MaterialState.pressed)) {
return selectedColor?.withOpacity(0.1);
return (overlayColor ?? selectedColor)?.withOpacity(0.1);
}
if (states.contains(MaterialState.hovered)) {
return selectedColor?.withOpacity(0.08);
return (overlayColor ?? selectedColor)?.withOpacity(0.08);
}
if (states.contains(MaterialState.focused)) {
return selectedColor?.withOpacity(0.1);
return (overlayColor ?? selectedColor)?.withOpacity(0.1);
}
} else {
if (states.contains(MaterialState.pressed)) {
return unselectedColor?.withOpacity(0.1);
return (overlayColor ?? unselectedColor)?.withOpacity(0.1);
}
if (states.contains(MaterialState.hovered)) {
return unselectedColor?.withOpacity(0.08);
return (overlayColor ?? unselectedColor)?.withOpacity(0.08);
}
if (states.contains(MaterialState.focused)) {
return unselectedColor?.withOpacity(0.1);
return (overlayColor ?? unselectedColor)?.withOpacity(0.1);
}
}
return Colors.transparent;
Expand Down
52 changes: 35 additions & 17 deletions packages/flutter/lib/src/material/icon_button.dart
Original file line number Diff line number Diff line change
Expand Up @@ -573,9 +573,15 @@ class IconButton extends StatelessWidget {
/// [ButtonStyle.foregroundColor] value. Specify a value for [foregroundColor]
/// to specify the color of the button's icons. The [hoverColor], [focusColor]
/// and [highlightColor] colors are used to indicate the hover, focus,
/// and pressed states. Use [backgroundColor] for the button's background
/// fill color. Use [disabledForegroundColor] and [disabledBackgroundColor]
/// to specify the button's disabled icon and fill color.
/// and pressed states if [overlayColor] isn't specified.
///
/// If [overlayColor] is specified and its value is [Colors.transparent]
/// then the pressed/focused/hovered highlights are effectively defeated.
/// Otherwise a [MaterialStateProperty] with the same opacities as the
/// default is created.
///
/// Use [backgroundColor] for the button's background fill color. Use [disabledForegroundColor]
/// and [disabledBackgroundColor] to specify the button's disabled icon and fill color.
///
/// Similarly, the [enabledMouseCursor] and [disabledMouseCursor]
/// parameters are used to construct [ButtonStyle].mouseCursor.
Expand Down Expand Up @@ -611,6 +617,7 @@ class IconButton extends StatelessWidget {
Color? highlightColor,
Color? shadowColor,
Color? surfaceTintColor,
Color? overlayColor,
double? elevation,
Size? minimumSize,
Size? fixedSize,
Expand All @@ -629,20 +636,24 @@ class IconButton extends StatelessWidget {
InteractiveInkFeatureFactory? splashFactory,
}) {
final MaterialStateProperty<Color?>? buttonBackgroundColor = (backgroundColor == null && disabledBackgroundColor == null)
? null
: _IconButtonDefaultBackground(backgroundColor, disabledBackgroundColor);
? null
: _IconButtonDefaultBackground(backgroundColor, disabledBackgroundColor);
final MaterialStateProperty<Color?>? buttonForegroundColor = (foregroundColor == null && disabledForegroundColor == null)
? null
: _IconButtonDefaultForeground(foregroundColor, disabledForegroundColor);
final MaterialStateProperty<Color?>? overlayColorProp = (foregroundColor == null &&
hoverColor == null && focusColor == null && highlightColor == null && overlayColor == null)
? null
: _IconButtonDefaultForeground(foregroundColor, disabledForegroundColor);
final MaterialStateProperty<Color?>? overlayColor = (foregroundColor == null && hoverColor == null && focusColor == null && highlightColor == null)
? null
: _IconButtonDefaultOverlay(foregroundColor, focusColor, hoverColor, highlightColor);
: switch (overlayColor) {
(final Color overlayColor) when overlayColor.value == 0 => const MaterialStatePropertyAll<Color?>(Colors.transparent),
_ => _IconButtonDefaultOverlay(foregroundColor, focusColor, hoverColor, highlightColor, overlayColor),
};
final MaterialStateProperty<MouseCursor?> mouseCursor = _IconButtonDefaultMouseCursor(enabledMouseCursor, disabledMouseCursor);

return ButtonStyle(
backgroundColor: buttonBackgroundColor,
foregroundColor: buttonForegroundColor,
overlayColor: overlayColor,
overlayColor: overlayColorProp,
shadowColor: ButtonStyleButton.allOrNull<Color>(shadowColor),
surfaceTintColor: ButtonStyleButton.allOrNull<Color>(surfaceTintColor),
elevation: ButtonStyleButton.allOrNull<double>(elevation),
Expand Down Expand Up @@ -1023,34 +1034,41 @@ class _IconButtonDefaultForeground extends MaterialStateProperty<Color?> {

@immutable
class _IconButtonDefaultOverlay extends MaterialStateProperty<Color?> {
_IconButtonDefaultOverlay(this.foregroundColor, this.focusColor, this.hoverColor, this.highlightColor);
_IconButtonDefaultOverlay(
this.foregroundColor,
this.focusColor,
this.hoverColor,
this.highlightColor,
this.overlayColor,
);

final Color? foregroundColor;
final Color? focusColor;
final Color? hoverColor;
final Color? highlightColor;
final Color? overlayColor;

@override
Color? resolve(Set<MaterialState> states) {
if (states.contains(MaterialState.selected)) {
if (states.contains(MaterialState.pressed)) {
return highlightColor ?? foregroundColor?.withOpacity(0.1);
return highlightColor ?? (overlayColor ?? foregroundColor)?.withOpacity(0.1);
}
if (states.contains(MaterialState.hovered)) {
return hoverColor ?? foregroundColor?.withOpacity(0.08);
return hoverColor ?? (overlayColor ?? foregroundColor)?.withOpacity(0.08);
}
if (states.contains(MaterialState.focused)) {
return focusColor ?? foregroundColor?.withOpacity(0.1);
return focusColor ?? (overlayColor ?? foregroundColor)?.withOpacity(0.1);
}
}
if (states.contains(MaterialState.pressed)) {
return highlightColor ?? foregroundColor?.withOpacity(0.1);
return highlightColor ?? (overlayColor ?? foregroundColor)?.withOpacity(0.1);
}
if (states.contains(MaterialState.hovered)) {
return hoverColor ?? foregroundColor?.withOpacity(0.08);
return hoverColor ?? (overlayColor ?? foregroundColor)?.withOpacity(0.08);
}
if (states.contains(MaterialState.focused)) {
return focusColor ?? foregroundColor?.withOpacity(0.1);
return focusColor ?? (overlayColor ?? foregroundColor)?.withOpacity(0.1);
}
return null;
}
Expand Down
4 changes: 4 additions & 0 deletions packages/flutter/lib/src/material/menu_anchor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1022,6 +1022,7 @@ class MenuItemButton extends StatefulWidget {
Color? surfaceTintColor,
Color? iconColor,
TextStyle? textStyle,
Color? overlayColor,
double? elevation,
EdgeInsetsGeometry? padding,
Size? minimumSize,
Expand All @@ -1047,6 +1048,7 @@ class MenuItemButton extends StatefulWidget {
surfaceTintColor: surfaceTintColor,
iconColor: iconColor,
textStyle: textStyle,
overlayColor: overlayColor,
elevation: elevation,
padding: padding,
minimumSize: minimumSize,
Expand Down Expand Up @@ -1775,6 +1777,7 @@ class SubmenuButton extends StatefulWidget {
Color? surfaceTintColor,
Color? iconColor,
TextStyle? textStyle,
Color? overlayColor,
double? elevation,
EdgeInsetsGeometry? padding,
Size? minimumSize,
Expand All @@ -1800,6 +1803,7 @@ class SubmenuButton extends StatefulWidget {
surfaceTintColor: surfaceTintColor,
iconColor: iconColor,
textStyle: textStyle,
overlayColor: overlayColor,
elevation: elevation,
padding: padding,
minimumSize: minimumSize,
Expand Down
34 changes: 22 additions & 12 deletions packages/flutter/lib/src/material/segmented_button.dart
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,12 @@ class SegmentedButton<T> extends StatefulWidget {
///
/// The [foregroundColor], [selectedForegroundColor], and [disabledForegroundColor]
/// colors are used to create a [MaterialStateProperty] [ButtonStyle.foregroundColor],
/// and a derived [ButtonStyle.overlayColor].
/// and a derived [ButtonStyle.overlayColor] if [overlayColor] isn't specified.
///
/// If [overlayColor] is specified and its value is [Colors.transparent]
/// then the pressed/focused/hovered highlights are effectively defeated.
/// Otherwise a [MaterialStateProperty] with the same opacities as the
/// default is created.
///
/// The [backgroundColor], [selectedBackgroundColor] and [disabledBackgroundColor]
/// colors are used to create a [MaterialStateProperty] [ButtonStyle.backgroundColor].
Expand Down Expand Up @@ -261,6 +266,7 @@ class SegmentedButton<T> extends StatefulWidget {
Color? disabledBackgroundColor,
Color? shadowColor,
Color? surfaceTintColor,
Color? overlayColor,
double? elevation,
TextStyle? textStyle,
EdgeInsetsGeometry? padding,
Expand All @@ -286,9 +292,13 @@ class SegmentedButton<T> extends StatefulWidget {
(backgroundColor == null && disabledBackgroundColor == null && selectedBackgroundColor == null)
? null
: _SegmentButtonDefaultColor(backgroundColor, disabledBackgroundColor, selectedBackgroundColor);
final MaterialStateProperty<Color?>? overlayColor = (foregroundColor == null && selectedForegroundColor == null)
? null
: _SegmentedButtonDefaultsM3.resolveStateColor(foregroundColor, selectedForegroundColor);
final MaterialStateProperty<Color?>? overlayColorProp = (foregroundColor == null &&
selectedForegroundColor == null && overlayColor == null)
? null
: switch (overlayColor) {
(final Color overlayColor) when overlayColor.value == 0 => const MaterialStatePropertyAll<Color?>(Colors.transparent),
_ => _SegmentedButtonDefaultsM3.resolveStateColor(foregroundColor, selectedForegroundColor, overlayColor),
};
return TextButton.styleFrom(
textStyle: textStyle,
shadowColor: shadowColor,
Expand All @@ -311,7 +321,7 @@ class SegmentedButton<T> extends StatefulWidget {
).copyWith(
foregroundColor: foregroundColorProp,
backgroundColor: backgroundColorProp,
overlayColor: overlayColor,
overlayColor: overlayColorProp,
);
}

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

static MaterialStateProperty<Color?> resolveStateColor(Color? unselectedColor, Color? selectedColor){
static MaterialStateProperty<Color?> resolveStateColor(Color? unselectedColor, Color? selectedColor, Color? overlayColor){
return MaterialStateProperty.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.selected)) {
if (states.contains(MaterialState.pressed)) {
return selectedColor?.withOpacity(0.1);
return (overlayColor ?? selectedColor)?.withOpacity(0.1);
}
if (states.contains(MaterialState.hovered)) {
return selectedColor?.withOpacity(0.08);
return (overlayColor ?? selectedColor)?.withOpacity(0.08);
}
if (states.contains(MaterialState.focused)) {
return selectedColor?.withOpacity(0.1);
return (overlayColor ?? selectedColor)?.withOpacity(0.1);
}
} else {
if (states.contains(MaterialState.pressed)) {
return unselectedColor?.withOpacity(0.1);
return (overlayColor ?? unselectedColor)?.withOpacity(0.1);
}
if (states.contains(MaterialState.hovered)) {
return unselectedColor?.withOpacity(0.08);
return (overlayColor ?? unselectedColor)?.withOpacity(0.08);
}
if (states.contains(MaterialState.focused)) {
return unselectedColor?.withOpacity(0.1);
return (overlayColor ?? unselectedColor)?.withOpacity(0.1);
}
}
return Colors.transparent;
Expand Down
Loading

0 comments on commit fa85f69

Please sign in to comment.