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