diff --git a/packages/flutter/lib/src/material/time_picker.dart b/packages/flutter/lib/src/material/time_picker.dart index d2d9e428fd..e36e5a20c3 100644 --- a/packages/flutter/lib/src/material/time_picker.dart +++ b/packages/flutter/lib/src/material/time_picker.dart @@ -2384,6 +2384,7 @@ class _TimePickerDialogState extends State with RestorationMix overflowAlignment: OverflowBarAlignment.end, children: [ TextButton( + style: pickerTheme.cancelButtonStyle ?? defaultTheme.cancelButtonStyle, onPressed: _handleCancel, child: Text(widget.cancelText ?? (theme.useMaterial3 @@ -2391,6 +2392,7 @@ class _TimePickerDialogState extends State with RestorationMix : localizations.cancelButtonLabel.toUpperCase())), ), TextButton( + style: pickerTheme.confirmButtonStyle ?? defaultTheme.confirmButtonStyle, onPressed: _handleOk, child: Text(widget.confirmText ?? localizations.okButtonLabel), ), diff --git a/packages/flutter/lib/src/material/time_picker_theme.dart b/packages/flutter/lib/src/material/time_picker_theme.dart index cb18b26645..1d0a95776d 100644 --- a/packages/flutter/lib/src/material/time_picker_theme.dart +++ b/packages/flutter/lib/src/material/time_picker_theme.dart @@ -72,7 +72,7 @@ class TimePickerThemeData with Diagnosticable { /// The style of the cancel button of a [TimePickerDialog]. final ButtonStyle? cancelButtonStyle; - /// The style of the conform (OK) button of a [TimePickerDialog]. + /// The style of the confirm (OK) button of a [TimePickerDialog]. final ButtonStyle? confirmButtonStyle; /// The color and weight of the day period's outline. diff --git a/packages/flutter/test/material/time_picker_theme_test.dart b/packages/flutter/test/material/time_picker_theme_test.dart index 44b480702a..784333c917 100644 --- a/packages/flutter/test/material/time_picker_theme_test.dart +++ b/packages/flutter/test/material/time_picker_theme_test.dart @@ -20,22 +20,28 @@ void main() { test('TimePickerThemeData null fields by default', () { const TimePickerThemeData timePickerTheme = TimePickerThemeData(); expect(timePickerTheme.backgroundColor, null); - expect(timePickerTheme.hourMinuteTextColor, null); - expect(timePickerTheme.hourMinuteColor, null); - expect(timePickerTheme.dayPeriodTextColor, null); - expect(timePickerTheme.dayPeriodColor, null); - expect(timePickerTheme.dialHandColor, null); - expect(timePickerTheme.dialBackgroundColor, null); - expect(timePickerTheme.dialTextColor, null); - expect(timePickerTheme.entryModeIconColor, null); - expect(timePickerTheme.hourMinuteTextStyle, null); - expect(timePickerTheme.dayPeriodTextStyle, null); - expect(timePickerTheme.helpTextStyle, null); - expect(timePickerTheme.shape, null); - expect(timePickerTheme.hourMinuteShape, null); - expect(timePickerTheme.dayPeriodShape, null); + expect(timePickerTheme.cancelButtonStyle, null); + expect(timePickerTheme.confirmButtonStyle, null); expect(timePickerTheme.dayPeriodBorderSide, null); + expect(timePickerTheme.dayPeriodColor, null); + expect(timePickerTheme.dayPeriodShape, null); + expect(timePickerTheme.dayPeriodTextColor, null); + expect(timePickerTheme.dayPeriodTextStyle, null); + expect(timePickerTheme.dialBackgroundColor, null); + expect(timePickerTheme.dialHandColor, null); + expect(timePickerTheme.dialTextColor, null); + expect(timePickerTheme.dialTextStyle, null); + expect(timePickerTheme.elevation, null); + expect(timePickerTheme.entryModeIconColor, null); + expect(timePickerTheme.helpTextStyle, null); + expect(timePickerTheme.hourMinuteColor, null); + expect(timePickerTheme.hourMinuteShape, null); + expect(timePickerTheme.hourMinuteTextColor, null); + expect(timePickerTheme.hourMinuteTextStyle, null); expect(timePickerTheme.inputDecorationTheme, null); + expect(timePickerTheme.entryModeIconColor, null); + expect(timePickerTheme.padding, null); + expect(timePickerTheme.shape, null); }); testWidgets('Default TimePickerThemeData debugFillProperties', (WidgetTester tester) async { @@ -53,22 +59,36 @@ void main() { testWidgets('TimePickerThemeData implements debugFillProperties', (WidgetTester tester) async { final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder(); const TimePickerThemeData( - backgroundColor: Color(0xFFFFFFFF), - hourMinuteTextColor: Color(0xFFFFFFFF), - hourMinuteColor: Color(0xFFFFFFFF), - dayPeriodTextColor: Color(0xFFFFFFFF), - dayPeriodColor: Color(0xFFFFFFFF), - dialHandColor: Color(0xFFFFFFFF), - dialBackgroundColor: Color(0xFFFFFFFF), - dialTextColor: Color(0xFFFFFFFF), - entryModeIconColor: Color(0xFFFFFFFF), - hourMinuteTextStyle: TextStyle(), - dayPeriodTextStyle: TextStyle(), - helpTextStyle: TextStyle(), - shape: RoundedRectangleBorder(), - hourMinuteShape: RoundedRectangleBorder(), - dayPeriodShape: RoundedRectangleBorder(), - dayPeriodBorderSide: BorderSide(), + backgroundColor: Color(0xfffffff0), + cancelButtonStyle: ButtonStyle(foregroundColor: MaterialStatePropertyAll(Color(0xfffffff1))), + confirmButtonStyle: ButtonStyle(foregroundColor: MaterialStatePropertyAll(Color(0xfffffff2))), + dayPeriodBorderSide: BorderSide(color: Color(0xfffffff3)), + dayPeriodColor: Color(0xfffffff4), + dayPeriodShape: RoundedRectangleBorder( + side: BorderSide(color: Color(0xfffffff5)), + ), + dayPeriodTextColor: Color(0xfffffff6), + dayPeriodTextStyle: TextStyle(color: Color(0xfffffff7)), + dialBackgroundColor: Color(0xfffffff8), + dialHandColor: Color(0xfffffff9), + dialTextColor: Color(0xfffffffa), + dialTextStyle: TextStyle(color: Color(0xfffffffb)), + elevation: 1.0, + entryModeIconColor: Color(0xfffffffc), + helpTextStyle: TextStyle(color: Color(0xfffffffd)), + hourMinuteColor: Color(0xfffffffe), + hourMinuteShape: RoundedRectangleBorder( + side: BorderSide(color: Color(0xffffffff)), + ), + hourMinuteTextColor: Color(0xfffffff0), + hourMinuteTextStyle: TextStyle(color: Color(0xfffffff1)), + inputDecorationTheme: InputDecorationTheme( + labelStyle: TextStyle(color: Color(0xfffffff2)), + ), + padding: EdgeInsets.all(1.0), + shape: RoundedRectangleBorder( + side: BorderSide(color: Color(0xfffffff3)), + ), ).debugFillProperties(builder); final List description = builder.properties @@ -76,24 +96,30 @@ void main() { .map((DiagnosticsNode node) => node.toString()) .toList(); - expect(description, [ - 'backgroundColor: Color(0xffffffff)', - 'dayPeriodBorderSide: BorderSide', - 'dayPeriodColor: Color(0xffffffff)', - 'dayPeriodShape: RoundedRectangleBorder(BorderSide(width: 0.0, style: none), BorderRadius.zero)', - 'dayPeriodTextColor: Color(0xffffffff)', - 'dayPeriodTextStyle: TextStyle()', - 'dialBackgroundColor: Color(0xffffffff)', - 'dialHandColor: Color(0xffffffff)', - 'dialTextColor: Color(0xffffffff)', - 'entryModeIconColor: Color(0xffffffff)', - 'helpTextStyle: TextStyle()', - 'hourMinuteColor: Color(0xffffffff)', - 'hourMinuteShape: RoundedRectangleBorder(BorderSide(width: 0.0, style: none), BorderRadius.zero)', - 'hourMinuteTextColor: Color(0xffffffff)', - 'hourMinuteTextStyle: TextStyle()', - 'shape: RoundedRectangleBorder(BorderSide(width: 0.0, style: none), BorderRadius.zero)' - ]); + expect(description, equalsIgnoringHashCodes([ + 'backgroundColor: Color(0xfffffff0)', + 'cancelButtonStyle: ButtonStyle#00000(foregroundColor: MaterialStatePropertyAll(Color(0xfffffff1)))', + 'confirmButtonStyle: ButtonStyle#00000(foregroundColor: MaterialStatePropertyAll(Color(0xfffffff2)))', + 'dayPeriodBorderSide: BorderSide(color: Color(0xfffffff3))', + 'dayPeriodColor: Color(0xfffffff4)', + 'dayPeriodShape: RoundedRectangleBorder(BorderSide(color: Color(0xfffffff5)), BorderRadius.zero)', + 'dayPeriodTextColor: Color(0xfffffff6)', + 'dayPeriodTextStyle: TextStyle(inherit: true, color: Color(0xfffffff7))', + 'dialBackgroundColor: Color(0xfffffff8)', + 'dialHandColor: Color(0xfffffff9)', + 'dialTextColor: Color(0xfffffffa)', + 'dialTextStyle: TextStyle(inherit: true, color: Color(0xfffffffb))', + 'elevation: 1.0', + 'entryModeIconColor: Color(0xfffffffc)', + 'helpTextStyle: TextStyle(inherit: true, color: Color(0xfffffffd))', + 'hourMinuteColor: Color(0xfffffffe)', + 'hourMinuteShape: RoundedRectangleBorder(BorderSide(color: Color(0xffffffff)), BorderRadius.zero)', + 'hourMinuteTextColor: Color(0xfffffff0)', + 'hourMinuteTextStyle: TextStyle(inherit: true, color: Color(0xfffffff1))', + 'inputDecorationTheme: InputDecorationTheme#ff861(labelStyle: TextStyle(inherit: true, color: Color(0xfffffff2)))', + 'padding: EdgeInsets.all(1.0)', + 'shape: RoundedRectangleBorder(BorderSide(color: Color(0xfffffff3)), BorderRadius.zero)' + ])); }); testWidgets('Material2 - Passing no TimePickerThemeData uses defaults', (WidgetTester tester) async { @@ -221,6 +247,12 @@ void main() { entryModeIconButton.color, defaultTheme.colorScheme.onSurface.withOpacity(0.6), ); + + final ButtonStyle cancelButtonStyle = _actionButtonStyle(tester, 'CANCEL'); + expect(cancelButtonStyle.toString(), equalsIgnoringHashCodes(TextButton.styleFrom().toString())); + + final ButtonStyle confirmButtonStyle = _actionButtonStyle(tester, 'OK'); + expect(confirmButtonStyle.toString(), equalsIgnoringHashCodes(TextButton.styleFrom().toString())); }); testWidgets('Material3 - Passing no TimePickerThemeData uses defaults', (WidgetTester tester) async { @@ -363,6 +395,12 @@ void main() { final IconButton entryModeIconButton = _entryModeIconButton(tester); expect(entryModeIconButton.color, null); + + final ButtonStyle cancelButtonStyle = _actionButtonStyle(tester, 'Cancel'); + expect(cancelButtonStyle.toString(), equalsIgnoringHashCodes(TextButton.styleFrom().toString())); + + final ButtonStyle confirmButtonStyle = _actionButtonStyle(tester, 'OK'); + expect(confirmButtonStyle.toString(), equalsIgnoringHashCodes(TextButton.styleFrom().toString())); }); testWidgets('Material2 - Passing no TimePickerThemeData uses defaults - input mode', (WidgetTester tester) async { @@ -399,6 +437,12 @@ void main() { Typography.material2014().englishLike.displayMedium! .merge(defaultTheme.textTheme.displayMedium!.copyWith(color: defaultTheme.colorScheme.onSurface.withOpacity(0.36))) ); + + final ButtonStyle cancelButtonStyle = _actionButtonStyle(tester, 'CANCEL'); + expect(cancelButtonStyle.toString(), equalsIgnoringHashCodes(TextButton.styleFrom().toString())); + + final ButtonStyle confirmButtonStyle= _actionButtonStyle(tester, 'OK'); + expect(confirmButtonStyle.toString(), equalsIgnoringHashCodes(TextButton.styleFrom().toString())); }); testWidgets('Material3 - Passing no TimePickerThemeData uses defaults - input mode', (WidgetTester tester) async { @@ -438,6 +482,12 @@ void main() { hourDecoration.hintStyle, TextStyle(color: defaultTheme.colorScheme.onSurface.withOpacity(0.36)) ); + + final ButtonStyle cancelButtonStyle = _actionButtonStyle(tester, 'Cancel'); + expect(cancelButtonStyle.toString(), equalsIgnoringHashCodes(TextButton.styleFrom().toString())); + + final ButtonStyle confirmButtonStyle = _actionButtonStyle(tester, 'OK'); + expect(confirmButtonStyle.toString(), equalsIgnoringHashCodes(TextButton.styleFrom().toString())); }); testWidgets('Material2 - Time picker uses values from TimePickerThemeData', (WidgetTester tester) async { @@ -555,6 +605,12 @@ void main() { entryModeIconButton.color, timePickerTheme.entryModeIconColor, ); + + final ButtonStyle cancelButtonStyle = _actionButtonStyle(tester, 'CANCEL'); + expect(cancelButtonStyle.toString(), equalsIgnoringHashCodes(timePickerTheme.cancelButtonStyle.toString())); + + final ButtonStyle confirmButtonStyle = _actionButtonStyle(tester, 'OK'); + expect(confirmButtonStyle.toString(), equalsIgnoringHashCodes(timePickerTheme.confirmButtonStyle.toString())); }); testWidgets('Material3 - Time picker uses values from TimePickerThemeData', (WidgetTester tester) async { @@ -672,6 +728,12 @@ void main() { final IconButton entryModeIconButton = _entryModeIconButton(tester); expect(entryModeIconButton.color, null); + + final ButtonStyle cancelButtonStyle = _actionButtonStyle(tester, 'Cancel'); + expect(cancelButtonStyle.toString(), equalsIgnoringHashCodes(timePickerTheme.cancelButtonStyle.toString())); + + final ButtonStyle confirmButtonStyle = _actionButtonStyle(tester, 'OK'); + expect(confirmButtonStyle.toString(), equalsIgnoringHashCodes(timePickerTheme.confirmButtonStyle.toString())); }); testWidgets('Time picker uses values from TimePickerThemeData with InputDecorationTheme - input mode', (WidgetTester tester) async { @@ -713,6 +775,8 @@ TimePickerThemeData _timePickerTheme({bool includeInputDecoration = false}) { final MaterialStateColor materialStateColor = MaterialStateColor.resolveWith(getColor); return TimePickerThemeData( backgroundColor: Colors.orange, + cancelButtonStyle: TextButton.styleFrom(primary: Colors.red), + confirmButtonStyle: TextButton.styleFrom(primary: Colors.green), hourMinuteTextColor: materialStateColor, hourMinuteColor: materialStateColor, dayPeriodTextColor: materialStateColor, @@ -807,3 +871,7 @@ final Finder findDialPaint = find.descendant( of: find.byWidgetPredicate((Widget w) => '${w.runtimeType}' == '_Dial'), matching: find.byWidgetPredicate((Widget w) => w is CustomPaint), ); + +ButtonStyle _actionButtonStyle(WidgetTester tester, String text) { + return tester.widget(find.widgetWithText(TextButton, text)).style!; +}