Skip to content

Commit 8679aeb

Browse files
authored
Fix TimePicker input mode width for 12-hour format (flutter#122868)
Fix `TimePicker` input mode width for 12-hour format
1 parent 0117de4 commit 8679aeb

File tree

2 files changed

+164
-3
lines changed

2 files changed

+164
-3
lines changed

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2338,7 +2338,7 @@ class _TimePickerDialogState extends State<TimePickerDialog> with RestorationMix
23382338
break;
23392339
case TimeOfDayFormat.a_space_h_colon_mm:
23402340
case TimeOfDayFormat.h_colon_mm_space_a:
2341-
timePickerWidth = _kTimePickerMinInputSize.width;
2341+
timePickerWidth = _kTimePickerMinInputSize.width - (useMaterial3 ? 32 : 0);
23422342
break;
23432343
}
23442344
return Size(timePickerWidth, _kTimePickerMinInputSize.height);
@@ -2383,7 +2383,7 @@ class _TimePickerDialogState extends State<TimePickerDialog> with RestorationMix
23832383
break;
23842384
case TimeOfDayFormat.a_space_h_colon_mm:
23852385
case TimeOfDayFormat.h_colon_mm_space_a:
2386-
timePickerWidth = _kTimePickerInputSize.width;
2386+
timePickerWidth = _kTimePickerInputSize.width - (useMaterial3 ? 32 : 0);
23872387
break;
23882388
}
23892389
timePickerSize = Size(timePickerWidth, _kTimePickerInputSize.height);
@@ -2457,7 +2457,6 @@ class _TimePickerDialogState extends State<TimePickerDialog> with RestorationMix
24572457
tapTargetSizeOffset = const Offset(0, -12);
24582458
break;
24592459
}
2460-
24612460
final Size dialogSize = _dialogSize(context, useMaterial3: theme.useMaterial3) + tapTargetSizeOffset;
24622461
final Size minDialogSize = _minDialogSize(context, useMaterial3: theme.useMaterial3) + tapTargetSizeOffset;
24632462
return Dialog(

packages/flutter/test/material/time_picker_test.dart

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,10 @@ void main() {
281281
});
282282

283283
group('Dialog (${materialType.name})', () {
284+
Material getMaterialFromDialog(WidgetTester tester) {
285+
return tester.widget<Material>(find.descendant(of: find.byType(Dialog), matching: find.byType(Material)).first);
286+
}
287+
284288
testWidgets('Widgets have correct label capitalization', (WidgetTester tester) async {
285289
await startPicker(tester, (TimeOfDay? time) {}, materialType: materialType);
286290
expect(find.text(selectTimeString), findsOneWidget);
@@ -313,6 +317,84 @@ void main() {
313317

314318
switch (materialType) {
315319
case MaterialType.material2:
320+
testWidgets('Dialog size - dial mode', (WidgetTester tester) async {
321+
addTearDown(tester.view.reset);
322+
323+
const Size timePickerPortraitSize = Size(310, 468);
324+
const Size timePickerLandscapeSize = Size(524, 342);
325+
const Size timePickerLandscapeSizeM2 = Size(508, 300);
326+
const EdgeInsets padding = EdgeInsets.fromLTRB(8, 18, 8, 8);
327+
double width;
328+
double height;
329+
330+
// portrait
331+
tester.view.physicalSize = const Size(800, 800.5);
332+
tester.view.devicePixelRatio = 1;
333+
await mediaQueryBoilerplate(tester, materialType: materialType);
334+
335+
width = timePickerPortraitSize.width + padding.horizontal;
336+
height = timePickerPortraitSize.height + padding.vertical;
337+
expect(
338+
tester.getSize(find.byWidget(getMaterialFromDialog(tester))),
339+
Size(width, height),
340+
);
341+
342+
await tester.tap(find.text(okString)); // dismiss the dialog
343+
await tester.pumpAndSettle();
344+
345+
// landscape
346+
tester.view.physicalSize = const Size(800.5, 800);
347+
tester.view.devicePixelRatio = 1;
348+
await mediaQueryBoilerplate(
349+
tester,
350+
alwaysUse24HourFormat: true,
351+
materialType: materialType,
352+
);
353+
354+
width = timePickerLandscapeSize.width + padding.horizontal;
355+
height = timePickerLandscapeSizeM2.height + padding.vertical;
356+
expect(
357+
tester.getSize(find.byWidget(getMaterialFromDialog(tester))),
358+
Size(width, height),
359+
);
360+
});
361+
362+
testWidgets('Dialog size - input mode', (WidgetTester tester) async {
363+
const TimePickerEntryMode entryMode = TimePickerEntryMode.input;
364+
const Size timePickerInputSize = Size(312, 216);
365+
const Size dayPeriodPortraitSize = Size(52, 80);
366+
const EdgeInsets padding = EdgeInsets.fromLTRB(8, 18, 8, 8);
367+
final double height = timePickerInputSize.height + padding.vertical;
368+
double width;
369+
370+
await mediaQueryBoilerplate(
371+
tester,
372+
entryMode: entryMode,
373+
materialType: materialType,
374+
);
375+
376+
width = timePickerInputSize.width + padding.horizontal;
377+
expect(
378+
tester.getSize(find.byWidget(getMaterialFromDialog(tester))),
379+
Size(width, height),
380+
);
381+
382+
await tester.tap(find.text(okString)); // dismiss the dialog
383+
await tester.pumpAndSettle();
384+
385+
await mediaQueryBoilerplate(
386+
tester,
387+
alwaysUse24HourFormat: true,
388+
entryMode: entryMode,
389+
materialType: materialType,
390+
);
391+
width = timePickerInputSize.width - dayPeriodPortraitSize.width - 12 + padding.horizontal + 16;
392+
expect(
393+
tester.getSize(find.byWidget(getMaterialFromDialog(tester))),
394+
Size(width, height),
395+
);
396+
});
397+
316398
testWidgets('respects MediaQueryData.alwaysUse24HourFormat == true', (WidgetTester tester) async {
317399
await mediaQueryBoilerplate(tester, alwaysUse24HourFormat: true, materialType: materialType);
318400

@@ -333,6 +415,86 @@ void main() {
333415
});
334416
break;
335417
case MaterialType.material3:
418+
testWidgets('Dialog size - dial mode', (WidgetTester tester) async {
419+
addTearDown(tester.view.reset);
420+
421+
const Size timePickerPortraitSize = Size(310, 468);
422+
const Size timePickerLandscapeSize = Size(524, 342);
423+
const EdgeInsets padding = EdgeInsets.all(24.0);
424+
double width;
425+
double height;
426+
427+
// portrait
428+
tester.view.physicalSize = const Size(800, 800.5);
429+
tester.view.devicePixelRatio = 1;
430+
await mediaQueryBoilerplate(tester, materialType: materialType);
431+
432+
width = timePickerPortraitSize.width + padding.horizontal;
433+
height = timePickerPortraitSize.height + padding.vertical;
434+
expect(
435+
tester.getSize(find.byWidget(getMaterialFromDialog(tester))),
436+
Size(width, height),
437+
);
438+
439+
await tester.tap(find.text(okString)); // dismiss the dialog
440+
await tester.pumpAndSettle();
441+
442+
// landscape
443+
tester.view.physicalSize = const Size(800.5, 800);
444+
tester.view.devicePixelRatio = 1;
445+
await mediaQueryBoilerplate(
446+
tester,
447+
alwaysUse24HourFormat: true,
448+
materialType: materialType,
449+
);
450+
451+
width = timePickerLandscapeSize.width + padding.horizontal;
452+
height = timePickerLandscapeSize.height + padding.vertical;
453+
expect(
454+
tester.getSize(find.byWidget(getMaterialFromDialog(tester))),
455+
Size(width, height),
456+
);
457+
});
458+
459+
testWidgets('Dialog size - input mode', (WidgetTester tester) async {
460+
final ThemeData theme = ThemeData(useMaterial3: true);
461+
const TimePickerEntryMode entryMode = TimePickerEntryMode.input;
462+
const double textScaleFactor = 1.0;
463+
const Size timePickerMinInputSize = Size(312, 216);
464+
const Size dayPeriodPortraitSize = Size(52, 80);
465+
const EdgeInsets padding = EdgeInsets.all(24.0);
466+
final double height = timePickerMinInputSize.height * textScaleFactor + padding.vertical;
467+
double width;
468+
469+
await mediaQueryBoilerplate(
470+
tester,
471+
entryMode: entryMode,
472+
materialType: materialType,
473+
);
474+
475+
width = timePickerMinInputSize.width - (theme.useMaterial3 ? 32 : 0) + padding.horizontal;
476+
expect(
477+
tester.getSize(find.byWidget(getMaterialFromDialog(tester))),
478+
Size(width, height),
479+
);
480+
481+
await tester.tap(find.text(okString)); // dismiss the dialog
482+
await tester.pumpAndSettle();
483+
484+
await mediaQueryBoilerplate(
485+
tester,
486+
alwaysUse24HourFormat: true,
487+
entryMode: entryMode,
488+
materialType: materialType,
489+
);
490+
491+
width = timePickerMinInputSize.width - dayPeriodPortraitSize.width - 12 + padding.horizontal;
492+
expect(
493+
tester.getSize(find.byWidget(getMaterialFromDialog(tester))),
494+
Size(width, height),
495+
);
496+
});
497+
336498
testWidgets('respects MediaQueryData.alwaysUse24HourFormat == true', (WidgetTester tester) async {
337499
await mediaQueryBoilerplate(tester, alwaysUse24HourFormat: true, materialType: materialType);
338500

0 commit comments

Comments
 (0)