Unverified Commit d7a3a682 authored by Taha Tesser's avatar Taha Tesser Committed by GitHub

Fix `cancelButtonStyle` & `confirmButtonStyle` properties from...

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`)

![Screenshot 2023-08-18 at 14 57 37](https://github.com/flutter/flutter/assets/48603081/c95160e2-76a2-4bb5-84e0-3731fce19c0b)

### After (action buttons use the style from the `TimePickerTheme`)

![Screenshot 2023-08-18 at 14 57 18](https://github.com/flutter/flutter/assets/48603081/422d348a-bee2-4696-8d9a-5fce56191aaa)
parent 336d60d2
...@@ -2384,6 +2384,7 @@ class _TimePickerDialogState extends State<TimePickerDialog> with RestorationMix ...@@ -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 ...@@ -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 { ...@@ -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() { ...@@ -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.dayPeriodBorderSide, null);
expect(timePickerTheme.dayPeriodColor, null); expect(timePickerTheme.dayPeriodColor, null);
expect(timePickerTheme.dialHandColor, null); expect(timePickerTheme.dayPeriodShape, null);
expect(timePickerTheme.dayPeriodTextColor, null);
expect(timePickerTheme.dayPeriodTextStyle, null);
expect(timePickerTheme.dialBackgroundColor, null); expect(timePickerTheme.dialBackgroundColor, null);
expect(timePickerTheme.dialHandColor, null);
expect(timePickerTheme.dialTextColor, null); expect(timePickerTheme.dialTextColor, null);
expect(timePickerTheme.dialTextStyle, null);
expect(timePickerTheme.elevation, null);
expect(timePickerTheme.entryModeIconColor, null); expect(timePickerTheme.entryModeIconColor, null);
expect(timePickerTheme.hourMinuteTextStyle, null);
expect(timePickerTheme.dayPeriodTextStyle, null);
expect(timePickerTheme.helpTextStyle, null); expect(timePickerTheme.helpTextStyle, null);
expect(timePickerTheme.shape, null); expect(timePickerTheme.hourMinuteColor, null);
expect(timePickerTheme.hourMinuteShape, null); expect(timePickerTheme.hourMinuteShape, null);
expect(timePickerTheme.dayPeriodShape, null); expect(timePickerTheme.hourMinuteTextColor, null);
expect(timePickerTheme.dayPeriodBorderSide, 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() { ...@@ -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() { ...@@ -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() { ...@@ -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() { ...@@ -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() { ...@@ -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() { ...@@ -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() { ...@@ -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() { ...@@ -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}) { ...@@ -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( ...@@ -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!;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment