Fix TimePicker
hour and minute inputs are resized on error (#154008)
Fixes [Defining inputDecorationTheme in TimePickerThemeData Causes Misalignment of Hour and Minute Input Boxes](https://github.com/flutter/flutter/issues/153549) ### Code sample <details> <summary>expand to view the code sample</summary> ```dart import 'package:flutter/material.dart'; void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, theme: ThemeData( timePickerTheme: const TimePickerThemeData( inputDecorationTheme: InputDecorationTheme(), ), ), home: Scaffold( body: Center( child: Builder(builder: (BuildContext context) { return ElevatedButton( onPressed: () async { await showTimePicker( context: context, initialEntryMode: TimePickerEntryMode.input, initialTime: TimeOfDay.now(), ); }, child: const Text('Show Time Picker'), ); }), ), ), ); } } ``` </details> ### Before <img width="578" alt="Screenshot 2024-08-23 at 16 49 25" src="https://github.com/user-attachments/assets/f5da2495-551e-4110-85ea-120323cd38d2"> ### After <img width="578" alt="Screenshot 2024-08-23 at 16 51 03" src="https://github.com/user-attachments/assets/80224a10-e9d2-46d1-b2eb-f16358699744">
This commit is contained in:
parent
b2de4dfc2b
commit
d7b092e42d
@ -331,7 +331,7 @@ class _${blockName}DefaultsM3 extends _TimePickerDefaults {
|
||||
// TODO(rami-a): Remove this workaround once
|
||||
// https://github.com/flutter/flutter/issues/54104
|
||||
// is fixed.
|
||||
errorStyle: const TextStyle(fontSize: 0, height: 0),
|
||||
errorStyle: const TextStyle(fontSize: 0),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -2047,7 +2047,14 @@ class _HourMinuteTextFieldState extends State<_HourMinuteTextField> with Restora
|
||||
final bool alwaysUse24HourFormat = MediaQuery.alwaysUse24HourFormatOf(context);
|
||||
|
||||
final InputDecorationTheme inputDecorationTheme = timePickerTheme.inputDecorationTheme ?? defaultTheme.inputDecorationTheme;
|
||||
InputDecoration inputDecoration = const InputDecoration().applyDefaults(inputDecorationTheme);
|
||||
InputDecoration inputDecoration = InputDecoration(
|
||||
// Prevent the error text from appearing when
|
||||
// timePickerTheme.inputDecorationTheme is used.
|
||||
// TODO(tahatesser): Remove this workaround once
|
||||
// https://github.com/flutter/flutter/issues/54104
|
||||
// is fixed.
|
||||
errorStyle: defaultTheme.inputDecorationTheme.errorStyle,
|
||||
).applyDefaults(inputDecorationTheme);
|
||||
// Remove the hint text when focused because the centered cursor
|
||||
// appears odd above the hint text.
|
||||
final String? hintText = focusNode.hasFocus ? null : _formattedValue;
|
||||
@ -3341,7 +3348,7 @@ class _TimePickerDefaultsM2 extends _TimePickerDefaults {
|
||||
// TODO(rami-a): Remove this workaround once
|
||||
// https://github.com/flutter/flutter/issues/54104
|
||||
// is fixed.
|
||||
errorStyle: const TextStyle(fontSize: 0, height: 0),
|
||||
errorStyle: const TextStyle(fontSize: 0, height: 1),
|
||||
);
|
||||
}
|
||||
|
||||
@ -3676,7 +3683,7 @@ class _TimePickerDefaultsM3 extends _TimePickerDefaults {
|
||||
// TODO(rami-a): Remove this workaround once
|
||||
// https://github.com/flutter/flutter/issues/54104
|
||||
// is fixed.
|
||||
errorStyle: const TextStyle(fontSize: 0, height: 0),
|
||||
errorStyle: const TextStyle(fontSize: 0),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -19,10 +19,18 @@ void main() {
|
||||
const String okString = 'OK';
|
||||
const String amString = 'AM';
|
||||
const String pmString = 'PM';
|
||||
|
||||
Material getMaterialFromDialog(WidgetTester tester) {
|
||||
return tester.widget<Material>(find.descendant(of: find.byType(Dialog), matching: find.byType(Material)).first);
|
||||
}
|
||||
|
||||
Finder findBorderPainter() {
|
||||
return find.descendant(
|
||||
of: find.byWidgetPredicate((Widget w) => '${w.runtimeType}' == '_BorderContainer'),
|
||||
matching: find.byWidgetPredicate((Widget w) => w is CustomPaint),
|
||||
);
|
||||
}
|
||||
|
||||
testWidgets('Material2 - Dialog size - dial mode', (WidgetTester tester) async {
|
||||
addTearDown(tester.view.reset);
|
||||
|
||||
@ -2013,6 +2021,43 @@ void main() {
|
||||
expect(paragraph.text.style!.color, theme.colorScheme.onSurface);
|
||||
expect(paragraph.text.style!.fontSize, 56.0);
|
||||
});
|
||||
|
||||
// This is a regression test for https://github.com/flutter/flutter/issues/153549.
|
||||
testWidgets('Time picker hour minute does not resize on error', (WidgetTester tester) async {
|
||||
await startPicker(
|
||||
entryMode: TimePickerEntryMode.input,
|
||||
tester,
|
||||
(TimeOfDay? value) { },
|
||||
);
|
||||
|
||||
expect(tester.getSize(findBorderPainter().first), const Size(96.0, 70.0));
|
||||
|
||||
// Enter invalid hour.
|
||||
await tester.enterText(find.byType(TextField).first, 'AB');
|
||||
await tester.tap(find.text(okString));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(tester.getSize(findBorderPainter().first), const Size(96.0, 70.0));
|
||||
});
|
||||
|
||||
// This is a regression test for https://github.com/flutter/flutter/issues/153549.
|
||||
testWidgets('Material2 - Time picker hour minute does not resize on error', (WidgetTester tester) async {
|
||||
await startPicker(
|
||||
entryMode: TimePickerEntryMode.input,
|
||||
tester,
|
||||
(TimeOfDay? value) { },
|
||||
materialType: MaterialType.material2,
|
||||
);
|
||||
|
||||
expect(tester.getSize(findBorderPainter().first), const Size(96.0, 70.0));
|
||||
|
||||
// Enter invalid hour.
|
||||
await tester.enterText(find.byType(TextField).first, 'AB');
|
||||
await tester.tap(find.text(okString));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(tester.getSize(findBorderPainter().first), const Size(96.0, 70.0));
|
||||
});
|
||||
}
|
||||
|
||||
final Finder findDialPaint = find.descendant(
|
||||
|
@ -858,6 +858,42 @@ void main() {
|
||||
expect(paragraph.text.style!.fontSize, 35.0);
|
||||
expect(paragraph.text.style!.fontStyle, FontStyle.italic);
|
||||
});
|
||||
|
||||
// This is a regression test for https://github.com/flutter/flutter/issues/153549.
|
||||
testWidgets('Time picker hour minute does not resize on error', (WidgetTester tester) async {
|
||||
final TimePickerThemeData timePickerTheme = _timePickerTheme(includeInputDecoration: true);
|
||||
final ThemeData theme = ThemeData(timePickerTheme: timePickerTheme);
|
||||
await tester.pumpWidget(_TimePickerLauncher(themeData: theme, entryMode: TimePickerEntryMode.input));
|
||||
await tester.tap(find.text('X'));
|
||||
await tester.pumpAndSettle(const Duration(seconds: 1));
|
||||
|
||||
expect(tester.getSize(findBorderPainter().first), const Size(96.0, 72.0));
|
||||
|
||||
// Enter invalid hour.
|
||||
await tester.enterText(find.byType(TextField).first, 'AB');
|
||||
await tester.tap(find.text('OK'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(tester.getSize(findBorderPainter().first), const Size(96.0, 72.0));
|
||||
});
|
||||
|
||||
// This is a regression test for https://github.com/flutter/flutter/issues/153549.
|
||||
testWidgets('Material2 - Time picker hour minute does not resize on error', (WidgetTester tester) async {
|
||||
final TimePickerThemeData timePickerTheme = _timePickerTheme(includeInputDecoration: true);
|
||||
final ThemeData theme = ThemeData(timePickerTheme: timePickerTheme, useMaterial3: false);
|
||||
await tester.pumpWidget(_TimePickerLauncher(themeData: theme, entryMode: TimePickerEntryMode.input));
|
||||
await tester.tap(find.text('X'));
|
||||
await tester.pumpAndSettle(const Duration(seconds: 1));
|
||||
|
||||
expect(tester.getSize(findBorderPainter().first), const Size(96.0, 70.0));
|
||||
|
||||
// Enter invalid hour.
|
||||
await tester.enterText(find.byType(TextField).first, 'AB');
|
||||
await tester.tap(find.text('OK'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(tester.getSize(findBorderPainter().first), const Size(96.0, 70.0));
|
||||
});
|
||||
}
|
||||
|
||||
final Color _selectedColor = Colors.green[100]!;
|
||||
@ -970,3 +1006,10 @@ final Finder findDialPaint = find.descendant(
|
||||
ButtonStyle _actionButtonStyle(WidgetTester tester, String text) {
|
||||
return tester.widget<TextButton>(find.widgetWithText(TextButton, text)).style!;
|
||||
}
|
||||
|
||||
Finder findBorderPainter() {
|
||||
return find.descendant(
|
||||
of: find.byWidgetPredicate((Widget w) => '${w.runtimeType}' == '_BorderContainer'),
|
||||
matching: find.byWidgetPredicate((Widget w) => w is CustomPaint),
|
||||
);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user