
fixes [`PopupMenuItem` adds redundant padding when using `ListItem`](https://github.com/flutter/flutter/issues/128553) ### Description - Fixed redundant `ListTile` padding when using `CheckedPopupMenuItem` or `PopupMenuItem` with the `ListTile` child for complex popup menu items as suggested in the docs. - Updated default horizontal padding for popup menu items. ### Code sample <details> <summary>expand to view the code sample</summary> ```dart import 'package:flutter/material.dart'; /// Flutter code sample for [PopupMenuButton]. // This is the type used by the popup menu below. enum SampleItem { itemOne, itemTwo, itemThree } void main() => runApp(const PopupMenuApp()); class PopupMenuApp extends StatelessWidget { const PopupMenuApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( theme: ThemeData(useMaterial3: true), home: const PopupMenuExample(), ); } } class PopupMenuExample extends StatefulWidget { const PopupMenuExample({super.key}); @override State<PopupMenuExample> createState() => _PopupMenuExampleState(); } class _PopupMenuExampleState extends State<PopupMenuExample> { SampleItem? selectedMenu; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('PopupMenuButton')), body: Center( child: SizedBox( width: 150, height: 100, child: Align( alignment: Alignment.topLeft, child: PopupMenuButton<SampleItem>( initialValue: selectedMenu, // Callback that sets the selected popup menu item. onSelected: (SampleItem item) { setState(() { selectedMenu = item; }); }, itemBuilder: (BuildContext context) => <PopupMenuEntry<SampleItem>>[ const PopupMenuItem<SampleItem>( value: SampleItem.itemOne, child: Text('PopupMenuItem'), ), const CheckedPopupMenuItem<SampleItem>( checked: true, value: SampleItem.itemTwo, child: Text('CheckedPopupMenuItem'), ), const PopupMenuItem<SampleItem>( value: SampleItem.itemOne, child: ListTile( leading: Icon(Icons.cloud), title: Text('ListTile'), contentPadding: EdgeInsets.zero, trailing: Icon(Icons.arrow_right_rounded), ), ), ], ), ), ), ), ); } } ``` </details> ### Before  - Default horizontal padding is the same as M2 (16.0), while the specs use a smaller value (12.0) - `ListTile` nested by default in `CheckedPopupMenuItem` has redundant padding - `PopupMenuItem` using `ListTile` as a child for complex menu items contains redundant padding.  ### After - Default horizontal padding is updated for Material 3. - `PopupMenuItem` & `CheckedPopupMenuItem` override `ListTile` padding (similar to how `ExpansionTile` overrides `ListTile` text and icon color. 
51 lines
1.8 KiB
Dart
51 lines
1.8 KiB
Dart
// Copyright 2014 The Flutter Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
import 'template.dart';
|
|
|
|
class PopupMenuTemplate extends TokenTemplate {
|
|
const PopupMenuTemplate(super.blockName, super.fileName, super.tokens, {
|
|
super.colorSchemePrefix = '_colors.',
|
|
super.textThemePrefix = '_textTheme.',
|
|
});
|
|
|
|
@override
|
|
String generate() => '''
|
|
class _${blockName}DefaultsM3 extends PopupMenuThemeData {
|
|
_${blockName}DefaultsM3(this.context)
|
|
: super(elevation: ${elevation('md.comp.menu.container')});
|
|
|
|
final BuildContext context;
|
|
late final ThemeData _theme = Theme.of(context);
|
|
late final ColorScheme _colors = _theme.colorScheme;
|
|
late final TextTheme _textTheme = _theme.textTheme;
|
|
|
|
@override MaterialStateProperty<TextStyle?>? get labelTextStyle {
|
|
return MaterialStateProperty.resolveWith((Set<MaterialState> states) {
|
|
final TextStyle style = _textTheme.labelLarge!;
|
|
if (states.contains(MaterialState.disabled)) {
|
|
return style.apply(color: ${componentColor('md.comp.list.list-item.disabled.label-text')});
|
|
}
|
|
return style.apply(color: ${componentColor('md.comp.list.list-item.label-text')});
|
|
});
|
|
}
|
|
|
|
@override
|
|
Color? get color => ${componentColor('md.comp.menu.container')};
|
|
|
|
@override
|
|
Color? get shadowColor => ${color("md.comp.menu.container.shadow-color")};
|
|
|
|
@override
|
|
Color? get surfaceTintColor => ${color("md.comp.menu.container.surface-tint-layer.color")};
|
|
|
|
@override
|
|
ShapeBorder? get shape => ${shape("md.comp.menu.container")};
|
|
|
|
// TODO(tahatesser): This is taken from https://m3.material.io/components/menus/specs
|
|
// Update this when the token is available.
|
|
static EdgeInsets menuHorizontalPadding = const EdgeInsets.symmetric(horizontal: 12.0);
|
|
}''';
|
|
}
|