diff --git a/packages/flutter/lib/src/material/popup_menu.dart b/packages/flutter/lib/src/material/popup_menu.dart index 7a3f7a5249..cc87623e63 100644 --- a/packages/flutter/lib/src/material/popup_menu.dart +++ b/packages/flutter/lib/src/material/popup_menu.dart @@ -399,6 +399,7 @@ class PopupMenuItemState> extends State { mouseCursor: _EffectiveMouseCursor(widget.mouseCursor, popupMenuTheme.mouseCursor), child: ListTileTheme.merge( contentPadding: EdgeInsets.zero, + titleTextStyle: style, child: item, ), ), diff --git a/packages/flutter/test/material/popup_menu_test.dart b/packages/flutter/test/material/popup_menu_test.dart index 60c576797d..1bfb2e028f 100644 --- a/packages/flutter/test/material/popup_menu_test.dart +++ b/packages/flutter/test/material/popup_menu_test.dart @@ -3423,14 +3423,14 @@ void main() { await tester.tapAt(const Offset(20.0, 20.0)); await tester.pumpAndSettle(); - // Test custom text theme text style. + // Test custom text theme. + const TextStyle customTextStyle = TextStyle( + fontSize: 20.0, + fontWeight: FontWeight.bold, + fontStyle: FontStyle.italic, + ); theme = theme.copyWith( - textTheme: theme.textTheme.copyWith( - labelLarge: const TextStyle( - fontSize: 20.0, - fontWeight: FontWeight.bold, - ) - ), + textTheme: const TextTheme(labelLarge: customTextStyle), ); await tester.pumpWidget(buildMenu()); @@ -3438,8 +3438,10 @@ void main() { await tester.tap(find.byKey(popupMenuButtonKey)); await tester.pumpAndSettle(); - expect(_labelStyle(tester, 'Item 1')!.fontSize, 20.0); - expect(_labelStyle(tester, 'Item 1')!.fontWeight, FontWeight.bold); + // Test custom text theme. + expect(_labelStyle(tester, 'Item 1')!.fontSize, customTextStyle.fontSize); + expect(_labelStyle(tester, 'Item 1')!.fontWeight, customTextStyle.fontWeight); + expect(_labelStyle(tester, 'Item 1')!.fontStyle, customTextStyle.fontStyle); }); testWidgets('CheckedPopupMenuItem.labelTextStyle resolve material states', (WidgetTester tester) async { @@ -3492,7 +3494,7 @@ void main() { ); }); - testWidgets('CheckedPopupMenuItem overrides redundant ListTile content padding', (WidgetTester tester) async { + testWidgets('CheckedPopupMenuItem overrides redundant ListTile.contentPadding', (WidgetTester tester) async { final Key popupMenuButtonKey = UniqueKey(); await tester.pumpWidget( MaterialApp( @@ -3537,7 +3539,7 @@ void main() { expect(getItemSafeArea('Item 1').minimum, EdgeInsets.zero); }); - testWidgets('PopupMenuItem overrides redundant ListTile content padding', (WidgetTester tester) async { + testWidgets('PopupMenuItem overrides redundant ListTile.contentPadding', (WidgetTester tester) async { final Key popupMenuButtonKey = UniqueKey(); await tester.pumpWidget( MaterialApp( @@ -3581,6 +3583,160 @@ void main() { expect(getItemSafeArea('Item 0').minimum, EdgeInsets.zero); expect(getItemSafeArea('Item 1').minimum, EdgeInsets.zero); }); + + testWidgets('Material3 - PopupMenuItem overrides ListTile.titleTextStyle', (WidgetTester tester) async { + final Key popupMenuButtonKey = UniqueKey(); + ThemeData theme = ThemeData(useMaterial3: true); + + Widget buildMenu() { + return MaterialApp( + theme: theme, + home: Scaffold( + body: Center( + child: PopupMenuButton( + key: popupMenuButtonKey, + child: const Text('button'), + onSelected: (String result) { }, + itemBuilder: (BuildContext context) { + return >[ + // Popup menu item with a Text widget. + const PopupMenuItem( + value: '0', + child: Text('Item 0'), + ), + // Popup menu item with a ListTile widget. + const PopupMenuItem( + value: '1', + child: ListTile(title: Text('Item 1')), + ), + ]; + }, + ), + ), + ), + ); + } + + await tester.pumpWidget(buildMenu()); + + // Show the menu. + await tester.tap(find.byKey(popupMenuButtonKey)); + await tester.pumpAndSettle(); + + // Test popup menu item with a Text widget. + expect(_labelStyle(tester, 'Item 0')!.fontSize, 14.0); + expect(_labelStyle(tester, 'Item 0')!.color, theme.colorScheme.onSurface); + + // Test popup menu item with a ListTile widget. + expect(_labelStyle(tester, 'Item 1')!.fontSize, 14.0); + expect(_labelStyle(tester, 'Item 1')!.color, theme.colorScheme.onSurface); + + // Close the menu. + await tester.tapAt(const Offset(20.0, 20.0)); + await tester.pumpAndSettle(); + + // Test custom text theme. + const TextStyle customTextStyle = TextStyle( + fontSize: 20.0, + fontWeight: FontWeight.bold, + fontStyle: FontStyle.italic, + ); + theme = theme.copyWith( + textTheme: const TextTheme(labelLarge: customTextStyle), + ); + await tester.pumpWidget(buildMenu()); + + // Show the menu. + await tester.tap(find.byKey(popupMenuButtonKey)); + await tester.pumpAndSettle(); + + // Test popup menu item with a Text widget with custom text theme. + expect(_labelStyle(tester, 'Item 0')!.fontSize, customTextStyle.fontSize); + expect(_labelStyle(tester, 'Item 0')!.fontWeight, customTextStyle.fontWeight); + expect(_labelStyle(tester, 'Item 0')!.fontStyle, customTextStyle.fontStyle); + + // Test popup menu item with a ListTile widget with custom text theme. + expect(_labelStyle(tester, 'Item 1')!.fontSize, customTextStyle.fontSize); + expect(_labelStyle(tester, 'Item 1')!.fontWeight, customTextStyle.fontWeight); + expect(_labelStyle(tester, 'Item 1')!.fontStyle, customTextStyle.fontStyle); + }); + + testWidgets('Material2 - PopupMenuItem overrides ListTile.titleTextStyle', (WidgetTester tester) async { + final Key popupMenuButtonKey = UniqueKey(); + ThemeData theme = ThemeData(useMaterial3: false); + + Widget buildMenu() { + return MaterialApp( + theme: theme, + home: Scaffold( + body: Center( + child: PopupMenuButton( + key: popupMenuButtonKey, + child: const Text('button'), + onSelected: (String result) { }, + itemBuilder: (BuildContext context) { + return >[ + // Popup menu item with a Text widget. + const PopupMenuItem( + value: '0', + child: Text('Item 0'), + ), + // Popup menu item with a ListTile widget. + const PopupMenuItem( + value: '1', + child: ListTile(title: Text('Item 1')), + ), + ]; + }, + ), + ), + ), + ); + } + + await tester.pumpWidget(buildMenu()); + + // Show the menu. + await tester.tap(find.byKey(popupMenuButtonKey)); + await tester.pumpAndSettle(); + + // Test popup menu item with a Text widget. + expect(_labelStyle(tester, 'Item 0')!.fontSize, 16.0); + expect(_labelStyle(tester, 'Item 0')!.color, theme.textTheme.subtitle1!.color); + + // Test popup menu item with a ListTile widget. + expect(_labelStyle(tester, 'Item 1')!.fontSize, 16.0); + expect(_labelStyle(tester, 'Item 1')!.color, theme.textTheme.subtitle1!.color); + + // Close the menu. + await tester.tapAt(const Offset(20.0, 20.0)); + await tester.pumpAndSettle(); + + // Test custom text theme. + const TextStyle customTextStyle = TextStyle( + fontSize: 20.0, + fontWeight: FontWeight.bold, + fontStyle: FontStyle.italic, + ); + theme = theme.copyWith( + textTheme: const TextTheme(subtitle1: customTextStyle), + ); + await tester.pumpWidget(buildMenu()); + + // Show the menu. + await tester.tap(find.byKey(popupMenuButtonKey)); + await tester.pumpAndSettle(); + + // Test popup menu item with a Text widget with custom text style. + expect(_labelStyle(tester, 'Item 0')!.fontSize, customTextStyle.fontSize); + expect(_labelStyle(tester, 'Item 0')!.fontWeight, customTextStyle.fontWeight); + expect(_labelStyle(tester, 'Item 0')!.fontStyle, customTextStyle.fontStyle); + + // Test popup menu item with a ListTile widget with custom text style. + expect(_labelStyle(tester, 'Item 1')!.fontSize, customTextStyle.fontSize); + expect(_labelStyle(tester, 'Item 1')!.fontWeight, customTextStyle.fontWeight); + expect(_labelStyle(tester, 'Item 1')!.fontStyle, customTextStyle.fontStyle); + }); } class TestApp extends StatelessWidget {