diff --git a/packages/flutter/lib/src/material/time_picker.dart b/packages/flutter/lib/src/material/time_picker.dart index 24ab9c9931..4ae5d13cd4 100644 --- a/packages/flutter/lib/src/material/time_picker.dart +++ b/packages/flutter/lib/src/material/time_picker.dart @@ -247,6 +247,8 @@ class _DayPeriodControl extends StatelessWidget { ); final bool layoutPortrait = orientation == Orientation.portrait; + final double buttonTextScaleFactor = math.min(MediaQuery.of(context).textScaleFactor, 2.0); + final Widget amButton = ConstrainedBox( constraints: _kMinTappableRegion, child: Material( @@ -261,7 +263,11 @@ class _DayPeriodControl extends StatelessWidget { heightFactor: 1, child: Semantics( selected: amSelected, - child: Text(materialLocalizations.anteMeridiemAbbreviation, style: amStyle), + child: Text( + materialLocalizations.anteMeridiemAbbreviation, + style: amStyle, + textScaleFactor: buttonTextScaleFactor, + ), ), ), ), @@ -284,7 +290,11 @@ class _DayPeriodControl extends StatelessWidget { heightFactor: 1, child: Semantics( selected: !amSelected, - child: Text(materialLocalizations.postMeridiemAbbreviation, style: pmStyle), + child: Text( + materialLocalizations.postMeridiemAbbreviation, + style: pmStyle, + textScaleFactor: buttonTextScaleFactor, + ), ), ), ), @@ -383,7 +393,12 @@ class _HourControl extends StatelessWidget { type: MaterialType.transparency, child: InkWell( onTap: Feedback.wrapForTap(() => fragmentContext.onModeChange(_TimePickerMode.hour), context), - child: Text(formattedHour, style: hourStyle, textAlign: TextAlign.end), + child: Text( + formattedHour, + style: hourStyle, + textAlign: TextAlign.end, + textScaleFactor: 1.0, + ), ), ), ), @@ -404,7 +419,7 @@ class _StringFragment extends StatelessWidget { @override Widget build(BuildContext context) { return ExcludeSemantics( - child: Text(value, style: fragmentContext.inactiveStyle), + child: Text(value, style: fragmentContext.inactiveStyle, textScaleFactor: 1.0), ); } } @@ -453,7 +468,7 @@ class _MinuteControl extends StatelessWidget { type: MaterialType.transparency, child: InkWell( onTap: Feedback.wrapForTap(() => fragmentContext.onModeChange(_TimePickerMode.minute), context), - child: Text(formattedMinute, style: minuteStyle, textAlign: TextAlign.start), + child: Text(formattedMinute, style: minuteStyle, textAlign: TextAlign.start, textScaleFactor: 1.0), ), ), ), @@ -1326,13 +1341,13 @@ class _DialState extends State<_Dial> with SingleTickerProviderStateMixin { _TappableLabel _buildTappableLabel(TextTheme textTheme, int value, String label, VoidCallback onTap) { final TextStyle style = textTheme.subhead; - // TODO(abarth): Handle textScaleFactor. - // https://github.com/flutter/flutter/issues/5939 + final double labelScaleFactor = math.min(MediaQuery.of(context).textScaleFactor, 2.0); return _TappableLabel( value: value, painter: TextPainter( text: TextSpan(style: style, text: label), textDirection: TextDirection.ltr, + textScaleFactor: labelScaleFactor, )..layout(), onTap: onTap, ); diff --git a/packages/flutter/test/material/time_picker_test.dart b/packages/flutter/test/material/time_picker_test.dart index d5a4d439cb..629fbddf1d 100644 --- a/packages/flutter/test/material/time_picker_test.dart +++ b/packages/flutter/test/material/time_picker_test.dart @@ -261,6 +261,7 @@ void _tests() { WidgetTester tester, bool alwaysUse24HourFormat, { TimeOfDay initialTime = const TimeOfDay(hour: 7, minute: 0), + double textScaleFactor = 1.0, }) async { await tester.pumpWidget( Localizations( @@ -270,7 +271,10 @@ void _tests() { DefaultWidgetsLocalizations.delegate, ], child: MediaQuery( - data: MediaQueryData(alwaysUse24HourFormat: alwaysUse24HourFormat), + data: MediaQueryData( + alwaysUse24HourFormat: alwaysUse24HourFormat, + textScaleFactor: textScaleFactor, + ), child: Material( child: Directionality( textDirection: TextDirection.ltr, @@ -689,6 +693,53 @@ void _tests() { expect(rootObserver.pickerCount, 0); expect(nestedObserver.pickerCount, 1); }); + + testWidgets('text scale affects certain elements and not others', + (WidgetTester tester) async { + await mediaQueryBoilerplate( + tester, + false, + textScaleFactor: 1.0, + initialTime: const TimeOfDay(hour: 7, minute: 41), + ); + await tester.tap(find.text('X')); + await tester.pumpAndSettle(); + + final double minutesDisplayHeight = tester.getSize(find.text('41')).height; + final double amHeight = tester.getSize(find.text('AM')).height; + + await tester.tap(find.text('OK')); // dismiss the dialog + await tester.pumpAndSettle(); + + // Verify that the time display is not affected by text scale. + await mediaQueryBoilerplate( + tester, + false, + textScaleFactor: 2.0, + initialTime: const TimeOfDay(hour: 7, minute: 41), + ); + await tester.tap(find.text('X')); + await tester.pumpAndSettle(); + + expect(tester.getSize(find.text('41')).height, equals(minutesDisplayHeight)); + expect(tester.getSize(find.text('AM')).height, equals(amHeight * 2)); + + await tester.tap(find.text('OK')); // dismiss the dialog + await tester.pumpAndSettle(); + + // Verify that text scale for AM/PM is at most 2x. + await mediaQueryBoilerplate( + tester, + false, + textScaleFactor: 3.0, + initialTime: const TimeOfDay(hour: 7, minute: 41), + ); + await tester.tap(find.text('X')); + await tester.pumpAndSettle(); + + expect(tester.getSize(find.text('41')).height, equals(minutesDisplayHeight)); + expect(tester.getSize(find.text('AM')).height, equals(amHeight * 2)); + }); } final Finder findDialPaint = find.descendant(