@@ -6,6 +6,7 @@ import 'package:flutter/foundation.dart';
6
6
import 'package:flutter/rendering.dart' ;
7
7
import 'package:flutter/widgets.dart' ;
8
8
9
+ import 'color_scheme.dart' ;
9
10
import 'constants.dart' ;
10
11
import 'debug.dart' ;
11
12
import 'divider.dart' ;
@@ -17,6 +18,7 @@ import 'material.dart';
17
18
import 'material_localizations.dart' ;
18
19
import 'material_state.dart' ;
19
20
import 'popup_menu_theme.dart' ;
21
+ import 'text_theme.dart' ;
20
22
import 'theme.dart' ;
21
23
import 'tooltip.dart' ;
22
24
@@ -224,6 +226,7 @@ class PopupMenuItem<T> extends PopupMenuEntry<T> {
224
226
this .height = kMinInteractiveDimension,
225
227
this .padding,
226
228
this .textStyle,
229
+ this .labelTextStyle,
227
230
this .mouseCursor,
228
231
required this .child,
229
232
}) : assert (enabled != null ),
@@ -263,6 +266,16 @@ class PopupMenuItem<T> extends PopupMenuEntry<T> {
263
266
/// of [ThemeData.textTheme] is used.
264
267
final TextStyle ? textStyle;
265
268
269
+ /// The label style of the popup menu item.
270
+ ///
271
+ /// When [ThemeData.useMaterial3] is true, this styles the text of the popup menu item.
272
+ ///
273
+ /// If this property is null, then [PopupMenuThemeData.labelTextStyle] is used.
274
+ /// If [PopupMenuThemeData.labelTextStyle] is also null, then [TextTheme.labelLarge]
275
+ /// is used with the [ColorScheme.onSurface] color when popup menu item is enabled and
276
+ /// the [ColorScheme.onSurface] color with 0.38 opacity when the popup menu item is disabled.
277
+ final MaterialStateProperty <TextStyle ?>? labelTextStyle;
278
+
266
279
/// {@template flutter.material.popupmenu.mouseCursor}
267
280
/// The cursor for a mouse pointer when it enters or is hovering over the
268
281
/// widget.
@@ -336,9 +349,20 @@ class PopupMenuItemState<T, W extends PopupMenuItem<T>> extends State<W> {
336
349
Widget build (BuildContext context) {
337
350
final ThemeData theme = Theme .of (context);
338
351
final PopupMenuThemeData popupMenuTheme = PopupMenuTheme .of (context);
339
- TextStyle style = widget.textStyle ?? popupMenuTheme.textStyle ?? theme.textTheme.titleMedium! ;
340
-
341
- if (! widget.enabled) {
352
+ final PopupMenuThemeData defaults = theme.useMaterial3 ? _PopupMenuDefaultsM3 (context) : _PopupMenuDefaultsM2 (context);
353
+ final Set <MaterialState > states = < MaterialState > {
354
+ if (! widget.enabled) MaterialState .disabled,
355
+ };
356
+
357
+ TextStyle style = theme.useMaterial3
358
+ ? (widget.labelTextStyle? .resolve (states)
359
+ ?? popupMenuTheme.labelTextStyle? .resolve (states)!
360
+ ?? defaults.labelTextStyle! .resolve (states)! )
361
+ : (widget.textStyle
362
+ ?? popupMenuTheme.textStyle
363
+ ?? defaults.textStyle! );
364
+
365
+ if (! widget.enabled && ! theme.useMaterial3) {
342
366
style = style.copyWith (color: theme.disabledColor);
343
367
}
344
368
@@ -537,7 +561,9 @@ class _PopupMenu<T> extends StatelessWidget {
537
561
Widget build (BuildContext context) {
538
562
final double unit = 1.0 / (route.items.length + 1.5 ); // 1.0 for the width and 0.5 for the last item's fade.
539
563
final List <Widget > children = < Widget > [];
564
+ final ThemeData theme = Theme .of (context);
540
565
final PopupMenuThemeData popupMenuTheme = PopupMenuTheme .of (context);
566
+ final PopupMenuThemeData defaults = theme.useMaterial3 ? _PopupMenuDefaultsM3 (context) : _PopupMenuDefaultsM2 (context);
541
567
542
568
for (int i = 0 ; i < route.items.length; i += 1 ) {
543
569
final double start = (i + 1 ) * unit;
@@ -598,11 +624,13 @@ class _PopupMenu<T> extends StatelessWidget {
598
624
return FadeTransition (
599
625
opacity: opacity.animate (route.animation! ),
600
626
child: Material (
601
- shape: route.shape ?? popupMenuTheme.shape,
602
- color: route.color ?? popupMenuTheme.color,
627
+ shape: route.shape ?? popupMenuTheme.shape ?? defaults.shape ,
628
+ color: route.color ?? popupMenuTheme.color ?? defaults.color ,
603
629
clipBehavior: clipBehavior,
604
630
type: MaterialType .card,
605
- elevation: route.elevation ?? popupMenuTheme.elevation ?? 8.0 ,
631
+ elevation: route.elevation ?? popupMenuTheme.elevation ?? defaults.elevation! ,
632
+ shadowColor: route.shadowColor ?? popupMenuTheme.shadowColor ?? defaults.shadowColor,
633
+ surfaceTintColor: route.surfaceTintColor ?? popupMenuTheme.surfaceTintColor ?? defaults.surfaceTintColor,
606
634
child: Align (
607
635
alignment: AlignmentDirectional .topEnd,
608
636
widthFactor: width.evaluate (route.animation! ),
@@ -757,6 +785,8 @@ class _PopupMenuRoute<T> extends PopupRoute<T> {
757
785
required this .items,
758
786
this .initialValue,
759
787
this .elevation,
788
+ this .surfaceTintColor,
789
+ this .shadowColor,
760
790
required this .barrierLabel,
761
791
this .semanticLabel,
762
792
this .shape,
@@ -771,6 +801,8 @@ class _PopupMenuRoute<T> extends PopupRoute<T> {
771
801
final List <Size ?> itemSizes;
772
802
final T ? initialValue;
773
803
final double ? elevation;
804
+ final Color ? surfaceTintColor;
805
+ final Color ? shadowColor;
774
806
final String ? semanticLabel;
775
807
final ShapeBorder ? shape;
776
808
final Color ? color;
@@ -911,6 +943,8 @@ Future<T?> showMenu<T>({
911
943
required List <PopupMenuEntry <T >> items,
912
944
T ? initialValue,
913
945
double ? elevation,
946
+ Color ? shadowColor,
947
+ Color ? surfaceTintColor,
914
948
String ? semanticLabel,
915
949
ShapeBorder ? shape,
916
950
Color ? color,
@@ -941,6 +975,8 @@ Future<T?> showMenu<T>({
941
975
items: items,
942
976
initialValue: initialValue,
943
977
elevation: elevation,
978
+ shadowColor: shadowColor,
979
+ surfaceTintColor: surfaceTintColor,
944
980
semanticLabel: semanticLabel,
945
981
barrierLabel: MaterialLocalizations .of (context).modalBarrierDismissLabel,
946
982
shape: shape,
@@ -1006,6 +1042,8 @@ class PopupMenuButton<T> extends StatefulWidget {
1006
1042
this .onCanceled,
1007
1043
this .tooltip,
1008
1044
this .elevation,
1045
+ this .shadowColor,
1046
+ this .surfaceTintColor,
1009
1047
this .padding = const EdgeInsets .all (8.0 ),
1010
1048
this .child,
1011
1049
this .splashRadius,
@@ -1058,6 +1096,22 @@ class PopupMenuButton<T> extends StatefulWidget {
1058
1096
/// Defaults to 8, the appropriate elevation for popup menus.
1059
1097
final double ? elevation;
1060
1098
1099
+ /// The color used to paint the shadow below the menu.
1100
+ ///
1101
+ /// If null then the ambient [PopupMenuThemeData.shadowColor] is used.
1102
+ /// If that is null too, then the overall theme's [ThemeData.shadowColor]
1103
+ /// (default black) is used.
1104
+ final Color ? shadowColor;
1105
+
1106
+ /// The color used as an overlay on [color] to indicate elevation.
1107
+ ///
1108
+ /// If null, [PopupMenuThemeData.surfaceTintColor] is used. If that
1109
+ /// is also null, the default value is [ColorScheme.surfaceTint] .
1110
+ ///
1111
+ /// See [Material.surfaceTintColor] for more details on how this
1112
+ /// overlay is applied.
1113
+ final Color ? surfaceTintColor;
1114
+
1061
1115
/// Matches IconButton's 8 dps padding by default. In some cases, notably where
1062
1116
/// this button appears as the trailing element of a list item, it's useful to be able
1063
1117
/// to set the padding to zero.
@@ -1207,6 +1261,8 @@ class PopupMenuButtonState<T> extends State<PopupMenuButton<T>> {
1207
1261
showMenu <T ?>(
1208
1262
context: context,
1209
1263
elevation: widget.elevation ?? popupMenuTheme.elevation,
1264
+ shadowColor: widget.shadowColor ?? popupMenuTheme.shadowColor,
1265
+ surfaceTintColor: widget.surfaceTintColor ?? popupMenuTheme.surfaceTintColor,
1210
1266
items: items,
1211
1267
initialValue: widget.initialValue,
1212
1268
position: position,
@@ -1240,6 +1296,7 @@ class PopupMenuButtonState<T> extends State<PopupMenuButton<T>> {
1240
1296
1241
1297
@override
1242
1298
Widget build (BuildContext context) {
1299
+ final IconThemeData iconTheme = IconTheme .of (context);
1243
1300
final bool enableFeedback = widget.enableFeedback
1244
1301
?? PopupMenuTheme .of (context).enableFeedback
1245
1302
?? true ;
@@ -1263,7 +1320,8 @@ class PopupMenuButtonState<T> extends State<PopupMenuButton<T>> {
1263
1320
icon: widget.icon ?? Icon (Icons .adaptive.more),
1264
1321
padding: widget.padding,
1265
1322
splashRadius: widget.splashRadius,
1266
- iconSize: widget.iconSize,
1323
+ iconSize: widget.iconSize ?? iconTheme.size,
1324
+ color: widget.color ?? iconTheme.color,
1267
1325
tooltip: widget.tooltip ?? MaterialLocalizations .of (context).showMenuTooltip,
1268
1326
onPressed: widget.enabled ? showButtonMenu : null ,
1269
1327
enableFeedback: enableFeedback,
@@ -1290,3 +1348,57 @@ class _EffectiveMouseCursor extends MaterialStateMouseCursor {
1290
1348
@override
1291
1349
String get debugDescription => 'MaterialStateMouseCursor(PopupMenuItemState)' ;
1292
1350
}
1351
+
1352
+ class _PopupMenuDefaultsM2 extends PopupMenuThemeData {
1353
+ _PopupMenuDefaultsM2 (this .context)
1354
+ : super (elevation: 8.0 );
1355
+
1356
+ final BuildContext context;
1357
+ late final ThemeData _theme = Theme .of (context);
1358
+ late final TextTheme _textTheme = _theme.textTheme;
1359
+
1360
+ @override
1361
+ TextStyle ? get textStyle => _textTheme.subtitle1;
1362
+ }
1363
+
1364
+ // BEGIN GENERATED TOKEN PROPERTIES - PopupMenu
1365
+
1366
+ // Do not edit by hand. The code between the "BEGIN GENERATED" and
1367
+ // "END GENERATED" comments are generated from data in the Material
1368
+ // Design token database by the script:
1369
+ // dev/tools/gen_defaults/bin/gen_defaults.dart.
1370
+
1371
+ // Token database version: v0_132
1372
+
1373
+ class _PopupMenuDefaultsM3 extends PopupMenuThemeData {
1374
+ _PopupMenuDefaultsM3 (this .context)
1375
+ : super (elevation: 3.0 );
1376
+
1377
+ final BuildContext context;
1378
+ late final ThemeData _theme = Theme .of (context);
1379
+ late final ColorScheme _colors = _theme.colorScheme;
1380
+ late final TextTheme _textTheme = _theme.textTheme;
1381
+
1382
+ @override MaterialStateProperty <TextStyle ?>? get labelTextStyle {
1383
+ return MaterialStateProperty .resolveWith ((Set <MaterialState > states) {
1384
+ final TextStyle style = _textTheme.labelLarge! ;
1385
+ if (states.contains (MaterialState .disabled)) {
1386
+ return style.apply (color: _colors.onSurface.withOpacity (0.38 ));
1387
+ }
1388
+ return style.apply (color: _colors.onSurface);
1389
+ });
1390
+ }
1391
+
1392
+ @override
1393
+ Color ? get color => _colors.surface;
1394
+
1395
+ @override
1396
+ Color ? get shadowColor => _colors.shadow;
1397
+
1398
+ @override
1399
+ Color ? get surfaceTintColor => _colors.surfaceTint;
1400
+
1401
+ @override
1402
+ ShapeBorder ? get shape => const RoundedRectangleBorder (borderRadius: BorderRadius .all (Radius .circular (4.0 )));
1403
+ }
1404
+ // END GENERATED TOKEN PROPERTIES - PopupMenu
0 commit comments