Fix cancelButtonStyle
& confirmButtonStyle
properties from TimePickerTheme
aren't working (#132843)
fixes [`TimePickerThemeData` action buttons styles aren't working](https://github.com/flutter/flutter/issues/132760) ### 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( useMaterial3: true, timePickerTheme: TimePickerThemeData( cancelButtonStyle: TextButton.styleFrom( shape: const RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(4)), side: BorderSide(color: Colors.red), ), backgroundColor: Colors.white, foregroundColor: Colors.red, elevation: 3, shadowColor: Colors.red, ), confirmButtonStyle: TextButton.styleFrom( shape: const RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(4)), ), backgroundColor: Colors.green[700], foregroundColor: Colors.white, elevation: 3, shadowColor: Colors.green[700], ), ), ), home: const Example(), ); } } class Example extends StatelessWidget { const Example({super.key}); @override Widget build(BuildContext context) { return Scaffold( body: Center( child: TimePickerDialog(initialTime: TimeOfDay.now()), ), ); } } ``` </details> ### Before (action buttons don't use the style from the `TimePickerTheme`)  ### After (action buttons use the style from the `TimePickerTheme`) 
This commit is contained in:
parent
336d60d29c
commit
d7a3a68275
@ -2384,6 +2384,7 @@ class _TimePickerDialogState extends State<TimePickerDialog> with RestorationMix
|
||||
overflowAlignment: OverflowBarAlignment.end,
|
||||
children: <Widget>[
|
||||
TextButton(
|
||||
style: pickerTheme.cancelButtonStyle ?? defaultTheme.cancelButtonStyle,
|
||||
onPressed: _handleCancel,
|
||||
child: Text(widget.cancelText ??
|
||||
(theme.useMaterial3
|
||||
@ -2391,6 +2392,7 @@ class _TimePickerDialogState extends State<TimePickerDialog> with RestorationMix
|
||||
: localizations.cancelButtonLabel.toUpperCase())),
|
||||
),
|
||||
TextButton(
|
||||
style: pickerTheme.confirmButtonStyle ?? defaultTheme.confirmButtonStyle,
|
||||
onPressed: _handleOk,
|
||||
child: Text(widget.confirmText ?? localizations.okButtonLabel),
|
||||
),
|
||||
|
@ -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.
|
||||
|
@ -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>(Color(0xfffffff1))),
|
||||
confirmButtonStyle: ButtonStyle(foregroundColor: MaterialStatePropertyAll<Color>(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<String> description = builder.properties
|
||||
@ -76,24 +96,30 @@ void main() {
|
||||
.map((DiagnosticsNode node) => node.toString())
|
||||
.toList();
|
||||
|
||||
expect(description, <String>[
|
||||
'backgroundColor: Color(0xffffffff)',
|
||||
'dayPeriodBorderSide: BorderSide',
|
||||
'dayPeriodColor: Color(0xffffffff)',
|
||||
'dayPeriodShape: RoundedRectangleBorder(BorderSide(width: 0.0, style: none), BorderRadius.zero)',
|
||||
'dayPeriodTextColor: Color(0xffffffff)',
|
||||
'dayPeriodTextStyle: TextStyle(<all styles inherited>)',
|
||||
'dialBackgroundColor: Color(0xffffffff)',
|
||||
'dialHandColor: Color(0xffffffff)',
|
||||
'dialTextColor: Color(0xffffffff)',
|
||||
'entryModeIconColor: Color(0xffffffff)',
|
||||
'helpTextStyle: TextStyle(<all styles inherited>)',
|
||||
'hourMinuteColor: Color(0xffffffff)',
|
||||
'hourMinuteShape: RoundedRectangleBorder(BorderSide(width: 0.0, style: none), BorderRadius.zero)',
|
||||
'hourMinuteTextColor: Color(0xffffffff)',
|
||||
'hourMinuteTextStyle: TextStyle(<all styles inherited>)',
|
||||
'shape: RoundedRectangleBorder(BorderSide(width: 0.0, style: none), BorderRadius.zero)'
|
||||
]);
|
||||
expect(description, equalsIgnoringHashCodes(<String>[
|
||||
'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<TextButton>(find.widgetWithText(TextButton, text)).style!;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user