Fix DropdownButtonFormField clips text when large text scale is used (#159975)
## Description This PR fixes `DropdownButtonFormField` text being clipped when using a large text scale. Before:  After:  This extend the fix from https://github.com/flutter/flutter/pull/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](https://github.com/flutter/flutter/issues/159971) ## Tests Adds 1 test. Updates 1 test.
This commit is contained in:
parent
9c960ff7da
commit
97ca57cf08
@ -1452,7 +1452,9 @@ class _DropdownButtonState<T> extends State<DropdownButton<T>> with WidgetsBindi
|
|||||||
double get _denseButtonHeight {
|
double get _denseButtonHeight {
|
||||||
final double fontSize =
|
final double fontSize =
|
||||||
_textStyle!.fontSize ?? Theme.of(context).textTheme.titleMedium!.fontSize!;
|
_textStyle!.fontSize ?? Theme.of(context).textTheme.titleMedium!.fontSize!;
|
||||||
final double scaledFontSize = MediaQuery.textScalerOf(context).scale(fontSize);
|
final double lineHeight =
|
||||||
|
_textStyle!.height ?? Theme.of(context).textTheme.titleMedium!.height ?? 1.0;
|
||||||
|
final double scaledFontSize = MediaQuery.textScalerOf(context).scale(fontSize * lineHeight);
|
||||||
return math.max(scaledFontSize, math.max(widget.iconSize, _kDenseButtonHeight));
|
return math.max(scaledFontSize, math.max(widget.iconSize, _kDenseButtonHeight));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -488,11 +488,65 @@ void main() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('DropdownButtonFormField with isDense:true does not clip large scale text', (
|
// Regression test for https://github.com/flutter/flutter/issues/159971.
|
||||||
|
testWidgets('DropdownButtonFormField does not clip large scale text', (
|
||||||
WidgetTester tester,
|
WidgetTester tester,
|
||||||
) async {
|
) async {
|
||||||
final Key buttonKey = UniqueKey();
|
final Key buttonKey = UniqueKey();
|
||||||
const String value = 'two';
|
const String value = 'two';
|
||||||
|
const double scaleFactor = 3.0;
|
||||||
|
|
||||||
|
final List<DropdownMenuItem<String>> dropdownItems =
|
||||||
|
menuItems.map<DropdownMenuItem<String>>((String item) {
|
||||||
|
return DropdownMenuItem<String>(
|
||||||
|
key: ValueKey<String>(item),
|
||||||
|
value: item,
|
||||||
|
child: Text(item, key: ValueKey<String>('${item}Text')),
|
||||||
|
);
|
||||||
|
}).toList();
|
||||||
|
|
||||||
|
await tester.pumpWidget(
|
||||||
|
TestApp(
|
||||||
|
textDirection: TextDirection.ltr,
|
||||||
|
child: Builder(
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return MediaQuery.withClampedTextScaling(
|
||||||
|
minScaleFactor: scaleFactor,
|
||||||
|
maxScaleFactor: scaleFactor,
|
||||||
|
child: Material(
|
||||||
|
child: Center(
|
||||||
|
child: DropdownButtonFormField<String>(
|
||||||
|
key: buttonKey,
|
||||||
|
value: value,
|
||||||
|
onChanged: onChanged,
|
||||||
|
items: dropdownItems,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
final BuildContext context = tester.element(find.byType(DropdownButton<String>));
|
||||||
|
final TextStyle style = Theme.of(context).textTheme.titleMedium!;
|
||||||
|
final double lineHeight = style.fontSize! * style.height!; // 16 * 1.5 = 24
|
||||||
|
final double labelHeight = lineHeight * scaleFactor; // 24 * 3.0 = 72
|
||||||
|
const double decorationVerticalPadding = 16.0;
|
||||||
|
final RenderBox box = tester.renderObject<RenderBox>(find.byType(DropdownButton<String>));
|
||||||
|
expect(box.size.height, labelHeight + decorationVerticalPadding);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Regression test for https://github.com/flutter/flutter/issues/159971.
|
||||||
|
testWidgets('DropdownButtonFormField with custom text style does not clip large scale text', (
|
||||||
|
WidgetTester tester,
|
||||||
|
) async {
|
||||||
|
final Key buttonKey = UniqueKey();
|
||||||
|
const String value = 'two';
|
||||||
|
const double scaleFactor = 3.0;
|
||||||
|
const double fontSize = 22;
|
||||||
|
const double fontHeight = 1.5;
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
TestApp(
|
TestApp(
|
||||||
@ -500,24 +554,21 @@ void main() {
|
|||||||
child: Builder(
|
child: Builder(
|
||||||
builder:
|
builder:
|
||||||
(BuildContext context) => MediaQuery.withClampedTextScaling(
|
(BuildContext context) => MediaQuery.withClampedTextScaling(
|
||||||
minScaleFactor: 3.0,
|
minScaleFactor: scaleFactor,
|
||||||
maxScaleFactor: 3.0,
|
maxScaleFactor: scaleFactor,
|
||||||
child: Material(
|
child: Material(
|
||||||
child: Center(
|
child: Center(
|
||||||
child: DropdownButtonFormField<String>(
|
child: DropdownButtonFormField<String>(
|
||||||
key: buttonKey,
|
key: buttonKey,
|
||||||
value: value,
|
value: value,
|
||||||
onChanged: onChanged,
|
onChanged: onChanged,
|
||||||
|
style: const TextStyle(fontSize: fontSize, height: fontHeight),
|
||||||
items:
|
items:
|
||||||
menuItems.map<DropdownMenuItem<String>>((String item) {
|
menuItems.map<DropdownMenuItem<String>>((String item) {
|
||||||
return DropdownMenuItem<String>(
|
return DropdownMenuItem<String>(
|
||||||
key: ValueKey<String>(item),
|
key: ValueKey<String>(item),
|
||||||
value: item,
|
value: item,
|
||||||
child: Text(
|
child: Text(item, key: ValueKey<String>('${item}Text')),
|
||||||
item,
|
|
||||||
key: ValueKey<String>('${item}Text'),
|
|
||||||
style: const TextStyle(fontSize: 20.0),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}).toList(),
|
}).toList(),
|
||||||
),
|
),
|
||||||
@ -528,8 +579,11 @@ void main() {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const double lineHeight = fontSize * fontHeight; // 22 * 1.5 = 33
|
||||||
|
const double labelHeight = lineHeight * scaleFactor; // 33 * 3.0 = 99
|
||||||
|
const double decorationVerticalPadding = 16.0;
|
||||||
final RenderBox box = tester.renderObject<RenderBox>(find.byType(DropdownButton<String>));
|
final RenderBox box = tester.renderObject<RenderBox>(find.byType(DropdownButton<String>));
|
||||||
expect(box.size.height, 64.0);
|
expect(box.size.height, labelHeight + decorationVerticalPadding);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('DropdownButtonFormField.isDense is true by default', (WidgetTester tester) async {
|
testWidgets('DropdownButtonFormField.isDense is true by default', (WidgetTester tester) async {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user