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
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.cancelButtonStyle, null);
expect(timePickerTheme.confirmButtonStyle, null);
expect(timePickerTheme.dayPeriodBorderSide, 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.dialHandColor, null);
expect(timePickerTheme.dialTextColor, null);
expect(timePickerTheme.dialTextStyle, null);
expect(timePickerTheme.elevation, null);
expect(timePickerTheme.entryModeIconColor, null);
expect(timePickerTheme.hourMinuteTextStyle, null);
expect(timePickerTheme.dayPeriodTextStyle, null);
expect(timePickerTheme.helpTextStyle, null);
expect(timePickerTheme.shape, null);
expect(timePickerTheme.hourMinuteColor, null);
expect(timePickerTheme.hourMinuteShape, null);
expect(timePickerTheme.dayPeriodShape, null);
expect(timePickerTheme.dayPeriodBorderSide, 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!;
}
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