Skip to content

Commit 37be384

Browse files
authored
Add visual density for menu default style (#114878)
Add visual density for menu default style
1 parent 13bbb52 commit 37be384

File tree

3 files changed

+155
-36
lines changed

3 files changed

+155
-36
lines changed

dev/tools/gen_defaults/lib/menu_template.dart

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,15 @@ class _MenuBarDefaultsM3 extends MenuStyle {
4343
4444
@override
4545
MaterialStateProperty<EdgeInsetsGeometry?>? get padding {
46-
return MaterialStatePropertyAll<EdgeInsetsGeometry>(
46+
return const MaterialStatePropertyAll<EdgeInsetsGeometry>(
4747
EdgeInsetsDirectional.symmetric(
48-
horizontal: math.max(
49-
_kTopLevelMenuHorizontalMinPadding,
50-
2 + Theme.of(context).visualDensity.baseSizeAdjustment.dx,
51-
),
48+
horizontal: _kTopLevelMenuHorizontalMinPadding
5249
),
5350
);
5451
}
52+
53+
@override
54+
VisualDensity get visualDensity => Theme.of(context).visualDensity;
5555
}
5656
5757
class _MenuButtonDefaultsM3 extends ButtonStyle {
@@ -188,10 +188,25 @@ class _MenuButtonDefaultsM3 extends ButtonStyle {
188188
189189
// The horizontal padding number comes from the spec.
190190
EdgeInsetsGeometry _scaledPadding(BuildContext context) {
191+
VisualDensity visualDensity = Theme.of(context).visualDensity;
192+
// When horizontal VisualDensity is greater than zero, set it to zero
193+
// because the [ButtonStyleButton] has already handle the padding based on the density.
194+
// However, the [ButtonStyleButton] doesn't allow the [VisualDensity] adjustment
195+
// to reduce the width of the left/right padding, so we need to handle it here if
196+
// the density is less than zero, such as on desktop platforms.
197+
if (visualDensity.horizontal > 0) {
198+
visualDensity = VisualDensity(vertical: visualDensity.vertical);
199+
}
191200
return ButtonStyleButton.scaledPadding(
192-
const EdgeInsets.symmetric(horizontal: 12),
193-
const EdgeInsets.symmetric(horizontal: 8),
194-
const EdgeInsets.symmetric(horizontal: 4),
201+
EdgeInsets.symmetric(horizontal: math.max(
202+
_kMenuViewPadding,
203+
_kLabelItemDefaultSpacing + visualDensity.baseSizeAdjustment.dx,
204+
)),
205+
EdgeInsets.symmetric(horizontal: math.max(
206+
_kMenuViewPadding,
207+
8 + visualDensity.baseSizeAdjustment.dx,
208+
)),
209+
const EdgeInsets.symmetric(horizontal: _kMenuViewPadding),
195210
MediaQuery.maybeTextScaleFactorOf(context) ?? 1,
196211
);
197212
}
@@ -229,15 +244,13 @@ class _MenuDefaultsM3 extends MenuStyle {
229244
230245
@override
231246
MaterialStateProperty<EdgeInsetsGeometry?>? get padding {
232-
return MaterialStatePropertyAll<EdgeInsetsGeometry>(
233-
EdgeInsetsDirectional.symmetric(
234-
vertical: math.max(
235-
_kMenuVerticalMinPadding,
236-
2 + Theme.of(context).visualDensity.baseSizeAdjustment.dy,
237-
),
238-
),
247+
return const MaterialStatePropertyAll<EdgeInsetsGeometry>(
248+
EdgeInsetsDirectional.symmetric(vertical: _kMenuVerticalMinPadding),
239249
);
240250
}
251+
252+
@override
253+
VisualDensity get visualDensity => Theme.of(context).visualDensity;
241254
}
242255
''';
243256
}

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

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3619,15 +3619,15 @@ class _MenuBarDefaultsM3 extends MenuStyle {
36193619

36203620
@override
36213621
MaterialStateProperty<EdgeInsetsGeometry?>? get padding {
3622-
return MaterialStatePropertyAll<EdgeInsetsGeometry>(
3622+
return const MaterialStatePropertyAll<EdgeInsetsGeometry>(
36233623
EdgeInsetsDirectional.symmetric(
3624-
horizontal: math.max(
3625-
_kTopLevelMenuHorizontalMinPadding,
3626-
2 + Theme.of(context).visualDensity.baseSizeAdjustment.dx,
3627-
),
3624+
horizontal: _kTopLevelMenuHorizontalMinPadding
36283625
),
36293626
);
36303627
}
3628+
3629+
@override
3630+
VisualDensity get visualDensity => Theme.of(context).visualDensity;
36313631
}
36323632

36333633
class _MenuButtonDefaultsM3 extends ButtonStyle {
@@ -3764,10 +3764,25 @@ class _MenuButtonDefaultsM3 extends ButtonStyle {
37643764

37653765
// The horizontal padding number comes from the spec.
37663766
EdgeInsetsGeometry _scaledPadding(BuildContext context) {
3767+
VisualDensity visualDensity = Theme.of(context).visualDensity;
3768+
// When horizontal VisualDensity is greater than zero, set it to zero
3769+
// because the [ButtonStyleButton] has already handle the padding based on the density.
3770+
// However, the [ButtonStyleButton] doesn't allow the [VisualDensity] adjustment
3771+
// to reduce the width of the left/right padding, so we need to handle it here if
3772+
// the density is less than zero, such as on desktop platforms.
3773+
if (visualDensity.horizontal > 0) {
3774+
visualDensity = VisualDensity(vertical: visualDensity.vertical);
3775+
}
37673776
return ButtonStyleButton.scaledPadding(
3768-
const EdgeInsets.symmetric(horizontal: 12),
3769-
const EdgeInsets.symmetric(horizontal: 8),
3770-
const EdgeInsets.symmetric(horizontal: 4),
3777+
EdgeInsets.symmetric(horizontal: math.max(
3778+
_kMenuViewPadding,
3779+
_kLabelItemDefaultSpacing + visualDensity.baseSizeAdjustment.dx,
3780+
)),
3781+
EdgeInsets.symmetric(horizontal: math.max(
3782+
_kMenuViewPadding,
3783+
8 + visualDensity.baseSizeAdjustment.dx,
3784+
)),
3785+
const EdgeInsets.symmetric(horizontal: _kMenuViewPadding),
37713786
MediaQuery.maybeTextScaleFactorOf(context) ?? 1,
37723787
);
37733788
}
@@ -3805,15 +3820,13 @@ class _MenuDefaultsM3 extends MenuStyle {
38053820

38063821
@override
38073822
MaterialStateProperty<EdgeInsetsGeometry?>? get padding {
3808-
return MaterialStatePropertyAll<EdgeInsetsGeometry>(
3809-
EdgeInsetsDirectional.symmetric(
3810-
vertical: math.max(
3811-
_kMenuVerticalMinPadding,
3812-
2 + Theme.of(context).visualDensity.baseSizeAdjustment.dy,
3813-
),
3814-
),
3823+
return const MaterialStatePropertyAll<EdgeInsetsGeometry>(
3824+
EdgeInsetsDirectional.symmetric(vertical: _kMenuVerticalMinPadding),
38153825
);
38163826
}
3827+
3828+
@override
3829+
VisualDensity get visualDensity => Theme.of(context).visualDensity;
38173830
}
38183831

38193832
// END GENERATED TOKEN PROPERTIES - Menu

packages/flutter/test/material/menu_anchor_test.dart

Lines changed: 99 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,99 @@ void main() {
147147
);
148148
}
149149

150+
testWidgets('Menu responds to density changes', (WidgetTester tester) async {
151+
Widget buildMenu({VisualDensity? visualDensity = VisualDensity.standard}) => MaterialApp(
152+
theme: ThemeData(visualDensity: visualDensity),
153+
home: Material(
154+
child: Column(
155+
children: <Widget>[
156+
MenuBar(
157+
children: createTestMenus(onPressed: onPressed),
158+
),
159+
const Expanded(child: Placeholder()),
160+
],
161+
),
162+
),
163+
);
164+
165+
await tester.pumpWidget(buildMenu());
166+
await tester.pump();
167+
168+
expect(tester.getRect(find.byType(MenuBar)), equals(const Rect.fromLTRB(145.0, 0.0, 655.0, 48.0)));
169+
170+
// Open and make sure things are the right size.
171+
await tester.tap(find.text(TestMenu.mainMenu1.label));
172+
await tester.pump();
173+
174+
expect(tester.getRect(find.byType(MenuBar)), equals(const Rect.fromLTRB(145.0, 0.0, 655.0, 48.0)));
175+
expect(
176+
tester.getRect(find.widgetWithText(MenuItemButton, TestMenu.subMenu10.label)),
177+
equals(const Rect.fromLTRB(257.0, 56.0, 471.0, 104.0)),
178+
);
179+
expect(
180+
tester.getRect(
181+
find.ancestor(of: find.text(TestMenu.subMenu10.label), matching: find.byType(Material)).at(1),
182+
),
183+
equals(const Rect.fromLTRB(257.0, 48.0, 471.0, 208.0)),
184+
);
185+
186+
// Test compact visual density (-2, -2)
187+
await tester.pumpWidget(Container());
188+
await tester.pumpWidget(buildMenu(visualDensity: VisualDensity.compact));
189+
await tester.pump();
190+
191+
// The original horizontal padding with standard visual density for menu buttons are 12 px, and the total length
192+
// for the menu bar is (655 - 145) = 510.
193+
// There are 4 buttons in the test menu bar, and with compact visual density,
194+
// the padding will reduce by abs(2 * (-2)) = 4. So the total length
195+
// now should reduce by abs(4 * 2 * (-4)) = 32, which would be 510 - 32 = 478, and
196+
// 478 = 639 - 161
197+
expect(tester.getRect(find.byType(MenuBar)), equals(const Rect.fromLTRB(161.0, 0.0, 639.0, 40.0)));
198+
199+
// Open and make sure things are the right size.
200+
await tester.tap(find.text(TestMenu.mainMenu1.label));
201+
await tester.pump();
202+
203+
expect(tester.getRect(find.byType(MenuBar)), equals(const Rect.fromLTRB(161.0, 0.0, 639.0, 40.0)));
204+
expect(
205+
tester.getRect(find.widgetWithText(MenuItemButton, TestMenu.subMenu10.label)),
206+
equals(const Rect.fromLTRB(265.0, 40.0, 467.0, 80.0)),
207+
);
208+
expect(
209+
tester.getRect(
210+
find.ancestor(of: find.text(TestMenu.subMenu10.label), matching: find.byType(Material)).at(1),
211+
),
212+
equals(const Rect.fromLTRB(265.0, 40.0, 467.0, 160.0)),
213+
);
214+
215+
await tester.pumpWidget(Container());
216+
await tester.pumpWidget(buildMenu(visualDensity: const VisualDensity(horizontal: 2.0, vertical: 2.0)));
217+
await tester.pump();
218+
219+
// Similarly, there are 4 buttons in the test menu bar, and with (2, 2) visual density,
220+
// the padding will increase by abs(2 * 4) = 8. So the total length for buttons
221+
// should increase by abs(4 * 2 * 8) = 64. The horizontal padding for the menu bar
222+
// increases by 2 * 8, so the total width increases to 510 + 64 + 16 = 590, and
223+
// 590 = 695 - 105
224+
expect(tester.getRect(find.byType(MenuBar)), equals(const Rect.fromLTRB(105.0, 0.0, 695.0, 72.0)));
225+
226+
// Open and make sure things are the right size.
227+
await tester.tap(find.text(TestMenu.mainMenu1.label));
228+
await tester.pump();
229+
230+
expect(tester.getRect(find.byType(MenuBar)), equals(const Rect.fromLTRB(105.0, 0.0, 695.0, 72.0)));
231+
expect(
232+
tester.getRect(find.widgetWithText(MenuItemButton, TestMenu.subMenu10.label)),
233+
equals(const Rect.fromLTRB(249.0, 80.0, 483.0, 136.0)),
234+
);
235+
expect(
236+
tester.getRect(
237+
find.ancestor(of: find.text(TestMenu.subMenu10.label), matching: find.byType(Material)).at(1),
238+
),
239+
equals(const Rect.fromLTRB(241.0, 64.0, 491.0, 264.0)),
240+
);
241+
});
242+
150243
testWidgets('menu defaults colors', (WidgetTester tester) async {
151244
final ThemeData themeData = ThemeData();
152245
await tester.pumpWidget(
@@ -2182,9 +2275,9 @@ void main() {
21822275
expect(
21832276
collectSubmenuRects(),
21842277
equals(const <Rect>[
2185-
Rect.fromLTRB(145.0, 0.0, 655.0, 40.0),
2186-
Rect.fromLTRB(257.0, 40.0, 467.0, 176.0),
2187-
Rect.fromLTRB(467.0, 80.0, 715.0, 256.0),
2278+
Rect.fromLTRB(161.0, 0.0, 639.0, 40.0),
2279+
Rect.fromLTRB(265.0, 40.0, 467.0, 160.0),
2280+
Rect.fromLTRB(467.0, 72.0, 707.0, 232.0),
21882281
]),
21892282
);
21902283
});
@@ -2198,9 +2291,9 @@ void main() {
21982291
expect(
21992292
collectSubmenuRects(),
22002293
equals(const <Rect>[
2201-
Rect.fromLTRB(145.0, 0.0, 655.0, 40.0),
2202-
Rect.fromLTRB(333.0, 40.0, 543.0, 176.0),
2203-
Rect.fromLTRB(85.0, 80.0, 333.0, 256.0),
2294+
Rect.fromLTRB(161.0, 0.0, 639.0, 40.0),
2295+
Rect.fromLTRB(333.0, 40.0, 535.0, 160.0),
2296+
Rect.fromLTRB(93.0, 72.0, 333.0, 232.0),
22042297
]),
22052298
);
22062299
});

0 commit comments

Comments
 (0)