Add cancelButtonStyle
& confirmButtonStyle
to the DatePickerThemeData
(#132847)
fixes [Unable to adjust the color for "Cancel" and "Ok" button in datePicker dialog](https://github.com/flutter/flutter/issues/127739) ### 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, datePickerTheme: DatePickerThemeData( cancelButtonStyle: TextButton.styleFrom( shape: const RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(16)), 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(16)), ), 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: DatePickerDialog( initialDate: DateTime.now(), firstDate: DateTime(2020), lastDate: DateTime(2030), ), ), ); } } ``` </details> ### Before Not possible to customize action buttons from the `DatePickerThemeData`. ### After 
This commit is contained in:
parent
2f2a10d540
commit
1e770c3808
@ -56,6 +56,16 @@ class _${blockName}DefaultsM3 extends DatePickerThemeData {
|
||||
@override
|
||||
Color? get backgroundColor => ${componentColor("md.comp.date-picker.modal.container")};
|
||||
|
||||
@override
|
||||
ButtonStyle get cancelButtonStyle {
|
||||
return TextButton.styleFrom();
|
||||
}
|
||||
|
||||
@override
|
||||
ButtonStyle get confirmButtonStyle {
|
||||
return TextButton.styleFrom();
|
||||
}
|
||||
|
||||
@override
|
||||
Color? get shadowColor => ${colorOrTransparent("md.comp.date-picker.modal.container.shadow-color")};
|
||||
|
||||
@ -231,8 +241,6 @@ class _${blockName}DefaultsM3 extends DatePickerThemeData {
|
||||
|
||||
@override
|
||||
TextStyle? get rangePickerHeaderHelpStyle => ${textStyle("md.comp.date-picker.modal.range-selection.month.subhead")};
|
||||
|
||||
|
||||
}
|
||||
''';
|
||||
}
|
||||
|
@ -543,6 +543,7 @@ class _DatePickerDialogState extends State<DatePickerDialog> with RestorationMix
|
||||
spacing: 8,
|
||||
children: <Widget>[
|
||||
TextButton(
|
||||
style: datePickerTheme.cancelButtonStyle ?? defaults.cancelButtonStyle,
|
||||
onPressed: _handleCancel,
|
||||
child: Text(widget.cancelText ?? (
|
||||
useMaterial3
|
||||
@ -551,6 +552,7 @@ class _DatePickerDialogState extends State<DatePickerDialog> with RestorationMix
|
||||
)),
|
||||
),
|
||||
TextButton(
|
||||
style: datePickerTheme.confirmButtonStyle ?? defaults.confirmButtonStyle,
|
||||
onPressed: _handleOk,
|
||||
child: Text(widget.confirmText ?? localizations.okButtonLabel),
|
||||
),
|
||||
|
@ -7,10 +7,12 @@ import 'dart:ui' show lerpDouble;
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
import 'button_style.dart';
|
||||
import 'color_scheme.dart';
|
||||
import 'colors.dart';
|
||||
import 'input_decorator.dart';
|
||||
import 'material_state.dart';
|
||||
import 'text_button.dart';
|
||||
import 'text_theme.dart';
|
||||
import 'theme.dart';
|
||||
|
||||
@ -70,6 +72,8 @@ class DatePickerThemeData with Diagnosticable {
|
||||
this.rangeSelectionOverlayColor,
|
||||
this.dividerColor,
|
||||
this.inputDecorationTheme,
|
||||
this.cancelButtonStyle,
|
||||
this.confirmButtonStyle,
|
||||
});
|
||||
|
||||
/// Overrides the default value of [Dialog.backgroundColor].
|
||||
@ -294,6 +298,12 @@ class DatePickerThemeData with Diagnosticable {
|
||||
/// If this is null, [ThemeData.inputDecorationTheme] is used instead.
|
||||
final InputDecorationTheme? inputDecorationTheme;
|
||||
|
||||
/// Overrides the default style of the cancel button of a [DatePickerDialog].
|
||||
final ButtonStyle? cancelButtonStyle;
|
||||
|
||||
/// Overrrides the default style of the confirm (OK) button of a [DatePickerDialog].
|
||||
final ButtonStyle? confirmButtonStyle;
|
||||
|
||||
/// Creates a copy of this object with the given fields replaced with the
|
||||
/// new values.
|
||||
DatePickerThemeData copyWith({
|
||||
@ -331,6 +341,8 @@ class DatePickerThemeData with Diagnosticable {
|
||||
MaterialStateProperty<Color?>? rangeSelectionOverlayColor,
|
||||
Color? dividerColor,
|
||||
InputDecorationTheme? inputDecorationTheme,
|
||||
ButtonStyle? cancelButtonStyle,
|
||||
ButtonStyle? confirmButtonStyle,
|
||||
}) {
|
||||
return DatePickerThemeData(
|
||||
backgroundColor: backgroundColor ?? this.backgroundColor,
|
||||
@ -367,6 +379,8 @@ class DatePickerThemeData with Diagnosticable {
|
||||
rangeSelectionOverlayColor: rangeSelectionOverlayColor ?? this.rangeSelectionOverlayColor,
|
||||
dividerColor: dividerColor ?? this.dividerColor,
|
||||
inputDecorationTheme: inputDecorationTheme ?? this.inputDecorationTheme,
|
||||
cancelButtonStyle: cancelButtonStyle ?? this.cancelButtonStyle,
|
||||
confirmButtonStyle: confirmButtonStyle ?? this.confirmButtonStyle,
|
||||
);
|
||||
}
|
||||
|
||||
@ -410,6 +424,8 @@ class DatePickerThemeData with Diagnosticable {
|
||||
rangeSelectionOverlayColor: MaterialStateProperty.lerp<Color?>(a?.rangeSelectionOverlayColor, b?.rangeSelectionOverlayColor, t, Color.lerp),
|
||||
dividerColor: Color.lerp(a?.dividerColor, b?.dividerColor, t),
|
||||
inputDecorationTheme: t < 0.5 ? a?.inputDecorationTheme : b?.inputDecorationTheme,
|
||||
cancelButtonStyle: ButtonStyle.lerp(a?.cancelButtonStyle, b?.cancelButtonStyle, t),
|
||||
confirmButtonStyle: ButtonStyle.lerp(a?.confirmButtonStyle, b?.confirmButtonStyle, t),
|
||||
);
|
||||
}
|
||||
|
||||
@ -459,6 +475,8 @@ class DatePickerThemeData with Diagnosticable {
|
||||
rangeSelectionOverlayColor,
|
||||
dividerColor,
|
||||
inputDecorationTheme,
|
||||
cancelButtonStyle,
|
||||
confirmButtonStyle,
|
||||
]);
|
||||
|
||||
@override
|
||||
@ -500,7 +518,9 @@ class DatePickerThemeData with Diagnosticable {
|
||||
&& other.rangeSelectionBackgroundColor == rangeSelectionBackgroundColor
|
||||
&& other.rangeSelectionOverlayColor == rangeSelectionOverlayColor
|
||||
&& other.dividerColor == dividerColor
|
||||
&& other.inputDecorationTheme == inputDecorationTheme;
|
||||
&& other.inputDecorationTheme == inputDecorationTheme
|
||||
&& other.cancelButtonStyle == cancelButtonStyle
|
||||
&& other.confirmButtonStyle == confirmButtonStyle;
|
||||
}
|
||||
|
||||
@override
|
||||
@ -540,6 +560,8 @@ class DatePickerThemeData with Diagnosticable {
|
||||
properties.add(DiagnosticsProperty<MaterialStateProperty<Color?>>('rangeSelectionOverlayColor', rangeSelectionOverlayColor, defaultValue: null));
|
||||
properties.add(ColorProperty('dividerColor', dividerColor, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<InputDecorationTheme>('inputDecorationTheme', inputDecorationTheme, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<ButtonStyle>('cancelButtonStyle', cancelButtonStyle, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<ButtonStyle>('confirmButtonStyle', confirmButtonStyle, defaultValue: null));
|
||||
}
|
||||
}
|
||||
|
||||
@ -658,6 +680,16 @@ class _DatePickerDefaultsM2 extends DatePickerThemeData {
|
||||
@override
|
||||
Color? get headerBackgroundColor => _isDark ? _colors.surface : _colors.primary;
|
||||
|
||||
@override
|
||||
ButtonStyle get cancelButtonStyle {
|
||||
return TextButton.styleFrom();
|
||||
}
|
||||
|
||||
@override
|
||||
ButtonStyle get confirmButtonStyle {
|
||||
return TextButton.styleFrom();
|
||||
}
|
||||
|
||||
@override
|
||||
Color? get headerForegroundColor => _isDark ? _colors.onSurface : _colors.onPrimary;
|
||||
|
||||
@ -818,6 +850,16 @@ class _DatePickerDefaultsM3 extends DatePickerThemeData {
|
||||
@override
|
||||
Color? get backgroundColor => _colors.surface;
|
||||
|
||||
@override
|
||||
ButtonStyle get cancelButtonStyle {
|
||||
return TextButton.styleFrom();
|
||||
}
|
||||
|
||||
@override
|
||||
ButtonStyle get confirmButtonStyle {
|
||||
return TextButton.styleFrom();
|
||||
}
|
||||
|
||||
@override
|
||||
Color? get shadowColor => Colors.transparent;
|
||||
|
||||
@ -993,8 +1035,6 @@ class _DatePickerDefaultsM3 extends DatePickerThemeData {
|
||||
|
||||
@override
|
||||
TextStyle? get rangePickerHeaderHelpStyle => _textTheme.titleSmall;
|
||||
|
||||
|
||||
}
|
||||
|
||||
// END GENERATED TOKEN PROPERTIES - DatePicker
|
||||
|
@ -46,7 +46,9 @@ void main() {
|
||||
inputDecorationTheme: InputDecorationTheme(
|
||||
fillColor: Color(0xffffff5f),
|
||||
border: UnderlineInputBorder(),
|
||||
)
|
||||
),
|
||||
cancelButtonStyle: ButtonStyle(foregroundColor: MaterialStatePropertyAll<Color>(Color(0xffffff6f))),
|
||||
confirmButtonStyle: ButtonStyle(foregroundColor: MaterialStatePropertyAll<Color>(Color(0xffffff7f))),
|
||||
);
|
||||
|
||||
Material findDialogMaterial(WidgetTester tester) {
|
||||
@ -77,6 +79,10 @@ void main() {
|
||||
return container.decoration as BoxDecoration?;
|
||||
}
|
||||
|
||||
ButtonStyle actionButtonStyle(WidgetTester tester, String text) {
|
||||
return tester.widget<TextButton>(find.widgetWithText(TextButton, text)).style!;
|
||||
}
|
||||
|
||||
const Size wideWindowSize = Size(1920.0, 1080.0);
|
||||
const Size narrowWindowSize = Size(1070.0, 1770.0);
|
||||
|
||||
@ -126,6 +132,8 @@ void main() {
|
||||
expect(theme.rangeSelectionOverlayColor, null);
|
||||
expect(theme.dividerColor, null);
|
||||
expect(theme.inputDecorationTheme, null);
|
||||
expect(theme.cancelButtonStyle, null);
|
||||
expect(theme.confirmButtonStyle, null);
|
||||
});
|
||||
|
||||
testWidgets('DatePickerTheme.defaults M3 defaults', (WidgetTester tester) async {
|
||||
@ -201,6 +209,8 @@ void main() {
|
||||
expect(m3.rangePickerHeaderHelpStyle, textTheme.titleSmall);
|
||||
expect(m3.dividerColor, null);
|
||||
expect(m3.inputDecorationTheme, null);
|
||||
expect(m3.cancelButtonStyle.toString(), equalsIgnoringHashCodes(TextButton.styleFrom().toString()));
|
||||
expect(m3.confirmButtonStyle.toString(), equalsIgnoringHashCodes(TextButton.styleFrom().toString()));
|
||||
});
|
||||
|
||||
testWidgets('DatePickerTheme.defaults M2 defaults', (WidgetTester tester) async {
|
||||
@ -268,6 +278,8 @@ void main() {
|
||||
expect(m2.rangePickerHeaderHelpStyle, textTheme.labelSmall);
|
||||
expect(m2.dividerColor, null);
|
||||
expect(m2.inputDecorationTheme, null);
|
||||
expect(m2.cancelButtonStyle.toString(), equalsIgnoringHashCodes(TextButton.styleFrom().toString()));
|
||||
expect(m2.confirmButtonStyle.toString(), equalsIgnoringHashCodes(TextButton.styleFrom().toString()));
|
||||
});
|
||||
|
||||
testWidgets('Default DatePickerThemeData debugFillProperties', (WidgetTester tester) async {
|
||||
@ -292,9 +304,7 @@ void main() {
|
||||
.map((DiagnosticsNode node) => node.toString())
|
||||
.toList();
|
||||
|
||||
expect(
|
||||
description,
|
||||
equalsIgnoringHashCodes(<String>[
|
||||
expect(description, equalsIgnoringHashCodes(<String>[
|
||||
'backgroundColor: Color(0xfffffff0)',
|
||||
'elevation: 6.0',
|
||||
'shadowColor: Color(0xfffffff1)',
|
||||
@ -328,9 +338,10 @@ void main() {
|
||||
'rangeSelectionBackgroundColor: Color(0xffffff2f)',
|
||||
'rangeSelectionOverlayColor: MaterialStatePropertyAll(Color(0xffffff3f))',
|
||||
'dividerColor: Color(0xffffff4f)',
|
||||
'inputDecorationTheme: InputDecorationTheme#00000(fillColor: Color(0xffffff5f), border: UnderlineInputBorder())'
|
||||
]),
|
||||
);
|
||||
'inputDecorationTheme: InputDecorationTheme#00000(fillColor: Color(0xffffff5f), border: UnderlineInputBorder())',
|
||||
'cancelButtonStyle: ButtonStyle#00000(foregroundColor: MaterialStatePropertyAll(Color(0xffffff6f)))',
|
||||
'confirmButtonStyle: ButtonStyle#00000(foregroundColor: MaterialStatePropertyAll(Color(0xffffff7f)))'
|
||||
]));
|
||||
});
|
||||
|
||||
testWidgets('DatePickerDialog uses ThemeData datePicker theme (calendar mode)', (WidgetTester tester) async {
|
||||
@ -426,6 +437,12 @@ void main() {
|
||||
await gesture.moveTo(tester.getCenter(find.text('2024')));
|
||||
await tester.pumpAndSettle();
|
||||
expect(inkFeatures, paints..rect(color: datePickerTheme.yearOverlayColor?.resolve(<MaterialState>{})));
|
||||
|
||||
final ButtonStyle cancelButtonStyle = actionButtonStyle(tester, 'Cancel');
|
||||
expect(cancelButtonStyle.toString(), equalsIgnoringHashCodes(datePickerTheme.cancelButtonStyle.toString()));
|
||||
|
||||
final ButtonStyle confirmButtonStyle = actionButtonStyle(tester, 'OK');
|
||||
expect(confirmButtonStyle.toString(), equalsIgnoringHashCodes(datePickerTheme.confirmButtonStyle.toString()));
|
||||
});
|
||||
|
||||
testWidgets('DatePickerDialog uses ThemeData datePicker theme (input mode)', (WidgetTester tester) async {
|
||||
@ -467,6 +484,12 @@ void main() {
|
||||
|
||||
final InputDecoration inputDecoration = tester.widget<TextField>(find.byType(TextField)).decoration!;
|
||||
expect(inputDecoration.fillColor, datePickerTheme.inputDecorationTheme?.fillColor);
|
||||
|
||||
final ButtonStyle cancelButtonStyle = actionButtonStyle(tester, 'Cancel');
|
||||
expect(cancelButtonStyle.toString(), equalsIgnoringHashCodes(datePickerTheme.cancelButtonStyle.toString()));
|
||||
|
||||
final ButtonStyle confirmButtonStyle = actionButtonStyle(tester, 'OK');
|
||||
expect(confirmButtonStyle.toString(), equalsIgnoringHashCodes(datePickerTheme.confirmButtonStyle.toString()));
|
||||
});
|
||||
|
||||
testWidgets('DateRangePickerDialog uses ThemeData datePicker theme', (WidgetTester tester) async {
|
||||
|
Loading…
x
Reference in New Issue
Block a user