Skip to content

Commit 794ee83

Browse files
blerouxphilip wasmund
authored and
philip wasmund
committed
Fix DropdownButtonFormField clips text when large text scale is used (flutter#159975)
## Description This PR fixes `DropdownButtonFormField` text being clipped when using a large text scale. Before: ![image](https://github.com/user-attachments/assets/6c4deed2-eb61-4c0a-912e-dba364013038) After: ![image](https://github.com/user-attachments/assets/1dee5cda-9885-47c1-92a6-afbbc2312266) This extend the fix from flutter#107201 which does not work properly with Material 3 (because of TextStyle.height being set for M3 default text styles). ## Related Issue Fixes [DropdownButtonFormField clips text when large text scale is used and useMaterial3 is true](flutter#159971) ## Tests Adds 1 test. Updates 1 test.
1 parent 239999b commit 794ee83

File tree

2 files changed

+66
-10
lines changed

2 files changed

+66
-10
lines changed

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1452,7 +1452,9 @@ class _DropdownButtonState<T> extends State<DropdownButton<T>> with WidgetsBindi
14521452
double get _denseButtonHeight {
14531453
final double fontSize =
14541454
_textStyle!.fontSize ?? Theme.of(context).textTheme.titleMedium!.fontSize!;
1455-
final double scaledFontSize = MediaQuery.textScalerOf(context).scale(fontSize);
1455+
final double lineHeight =
1456+
_textStyle!.height ?? Theme.of(context).textTheme.titleMedium!.height ?? 1.0;
1457+
final double scaledFontSize = MediaQuery.textScalerOf(context).scale(fontSize * lineHeight);
14561458
return math.max(scaledFontSize, math.max(widget.iconSize, _kDenseButtonHeight));
14571459
}
14581460

packages/flutter/test/material/dropdown_form_field_test.dart

Lines changed: 63 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -488,36 +488,87 @@ void main() {
488488
}
489489
});
490490

491-
testWidgets('DropdownButtonFormField with isDense:true does not clip large scale text', (
491+
// Regression test for https://github.com/flutter/flutter/issues/159971.
492+
testWidgets('DropdownButtonFormField does not clip large scale text', (
492493
WidgetTester tester,
493494
) async {
494495
final Key buttonKey = UniqueKey();
495496
const String value = 'two';
497+
const double scaleFactor = 3.0;
498+
499+
final List<DropdownMenuItem<String>> dropdownItems =
500+
menuItems.map<DropdownMenuItem<String>>((String item) {
501+
return DropdownMenuItem<String>(
502+
key: ValueKey<String>(item),
503+
value: item,
504+
child: Text(item, key: ValueKey<String>('${item}Text')),
505+
);
506+
}).toList();
507+
508+
await tester.pumpWidget(
509+
TestApp(
510+
textDirection: TextDirection.ltr,
511+
child: Builder(
512+
builder: (BuildContext context) {
513+
return MediaQuery.withClampedTextScaling(
514+
minScaleFactor: scaleFactor,
515+
maxScaleFactor: scaleFactor,
516+
child: Material(
517+
child: Center(
518+
child: DropdownButtonFormField<String>(
519+
key: buttonKey,
520+
value: value,
521+
onChanged: onChanged,
522+
items: dropdownItems,
523+
),
524+
),
525+
),
526+
);
527+
},
528+
),
529+
),
530+
);
531+
532+
final BuildContext context = tester.element(find.byType(DropdownButton<String>));
533+
final TextStyle style = Theme.of(context).textTheme.titleMedium!;
534+
final double lineHeight = style.fontSize! * style.height!; // 16 * 1.5 = 24
535+
final double labelHeight = lineHeight * scaleFactor; // 24 * 3.0 = 72
536+
const double decorationVerticalPadding = 16.0;
537+
final RenderBox box = tester.renderObject<RenderBox>(find.byType(DropdownButton<String>));
538+
expect(box.size.height, labelHeight + decorationVerticalPadding);
539+
});
540+
541+
// Regression test for https://github.com/flutter/flutter/issues/159971.
542+
testWidgets('DropdownButtonFormField with custom text style does not clip large scale text', (
543+
WidgetTester tester,
544+
) async {
545+
final Key buttonKey = UniqueKey();
546+
const String value = 'two';
547+
const double scaleFactor = 3.0;
548+
const double fontSize = 22;
549+
const double fontHeight = 1.5;
496550

497551
await tester.pumpWidget(
498552
TestApp(
499553
textDirection: TextDirection.ltr,
500554
child: Builder(
501555
builder:
502556
(BuildContext context) => MediaQuery.withClampedTextScaling(
503-
minScaleFactor: 3.0,
504-
maxScaleFactor: 3.0,
557+
minScaleFactor: scaleFactor,
558+
maxScaleFactor: scaleFactor,
505559
child: Material(
506560
child: Center(
507561
child: DropdownButtonFormField<String>(
508562
key: buttonKey,
509563
value: value,
510564
onChanged: onChanged,
565+
style: const TextStyle(fontSize: fontSize, height: fontHeight),
511566
items:
512567
menuItems.map<DropdownMenuItem<String>>((String item) {
513568
return DropdownMenuItem<String>(
514569
key: ValueKey<String>(item),
515570
value: item,
516-
child: Text(
517-
item,
518-
key: ValueKey<String>('${item}Text'),
519-
style: const TextStyle(fontSize: 20.0),
520-
),
571+
child: Text(item, key: ValueKey<String>('${item}Text')),
521572
);
522573
}).toList(),
523574
),
@@ -528,8 +579,11 @@ void main() {
528579
),
529580
);
530581

582+
const double lineHeight = fontSize * fontHeight; // 22 * 1.5 = 33
583+
const double labelHeight = lineHeight * scaleFactor; // 33 * 3.0 = 99
584+
const double decorationVerticalPadding = 16.0;
531585
final RenderBox box = tester.renderObject<RenderBox>(find.byType(DropdownButton<String>));
532-
expect(box.size.height, 64.0);
586+
expect(box.size.height, labelHeight + decorationVerticalPadding);
533587
});
534588

535589
testWidgets('DropdownButtonFormField.isDense is true by default', (WidgetTester tester) async {

0 commit comments

Comments
 (0)