Add DatePickerTheme.inputDecorationTheme
for the DatePicker with input mode. (#128950)
This commit is contained in:
parent
9c96357277
commit
32fe4d7f0a
@ -9,6 +9,7 @@ import 'package:flutter/widgets.dart';
|
||||
|
||||
import 'color_scheme.dart';
|
||||
import 'colors.dart';
|
||||
import 'input_decorator.dart';
|
||||
import 'material_state.dart';
|
||||
import 'text_theme.dart';
|
||||
import 'theme.dart';
|
||||
@ -68,6 +69,7 @@ class DatePickerThemeData with Diagnosticable {
|
||||
this.rangeSelectionBackgroundColor,
|
||||
this.rangeSelectionOverlayColor,
|
||||
this.dividerColor,
|
||||
this.inputDecorationTheme,
|
||||
});
|
||||
|
||||
/// Overrides the default value of [Dialog.backgroundColor].
|
||||
@ -288,6 +290,10 @@ class DatePickerThemeData with Diagnosticable {
|
||||
/// and vertical divider when the dialog is in landscape orientation.
|
||||
final Color? dividerColor;
|
||||
|
||||
/// Overrides the [InputDatePickerFormField]'s input decoration theme.
|
||||
/// If this is null, [ThemeData.inputDecorationTheme] is used instead.
|
||||
final InputDecorationTheme? inputDecorationTheme;
|
||||
|
||||
/// Creates a copy of this object with the given fields replaced with the
|
||||
/// new values.
|
||||
DatePickerThemeData copyWith({
|
||||
@ -324,6 +330,7 @@ class DatePickerThemeData with Diagnosticable {
|
||||
Color? rangeSelectionBackgroundColor,
|
||||
MaterialStateProperty<Color?>? rangeSelectionOverlayColor,
|
||||
Color? dividerColor,
|
||||
InputDecorationTheme? inputDecorationTheme,
|
||||
}) {
|
||||
return DatePickerThemeData(
|
||||
backgroundColor: backgroundColor ?? this.backgroundColor,
|
||||
@ -359,6 +366,7 @@ class DatePickerThemeData with Diagnosticable {
|
||||
rangeSelectionBackgroundColor: rangeSelectionBackgroundColor ?? this.rangeSelectionBackgroundColor,
|
||||
rangeSelectionOverlayColor: rangeSelectionOverlayColor ?? this.rangeSelectionOverlayColor,
|
||||
dividerColor: dividerColor ?? this.dividerColor,
|
||||
inputDecorationTheme: inputDecorationTheme ?? this.inputDecorationTheme,
|
||||
);
|
||||
}
|
||||
|
||||
@ -401,6 +409,7 @@ class DatePickerThemeData with Diagnosticable {
|
||||
rangeSelectionBackgroundColor: Color.lerp(a?.rangeSelectionBackgroundColor, b?.rangeSelectionBackgroundColor, t),
|
||||
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,
|
||||
);
|
||||
}
|
||||
|
||||
@ -449,6 +458,7 @@ class DatePickerThemeData with Diagnosticable {
|
||||
rangeSelectionBackgroundColor,
|
||||
rangeSelectionOverlayColor,
|
||||
dividerColor,
|
||||
inputDecorationTheme,
|
||||
]);
|
||||
|
||||
@override
|
||||
@ -489,7 +499,8 @@ class DatePickerThemeData with Diagnosticable {
|
||||
&& other.rangePickerHeaderHelpStyle == rangePickerHeaderHelpStyle
|
||||
&& other.rangeSelectionBackgroundColor == rangeSelectionBackgroundColor
|
||||
&& other.rangeSelectionOverlayColor == rangeSelectionOverlayColor
|
||||
&& other.dividerColor == dividerColor;
|
||||
&& other.dividerColor == dividerColor
|
||||
&& other.inputDecorationTheme == inputDecorationTheme;
|
||||
}
|
||||
|
||||
@override
|
||||
@ -528,6 +539,7 @@ class DatePickerThemeData with Diagnosticable {
|
||||
properties.add(ColorProperty('rangeSelectionBackgroundColor', rangeSelectionBackgroundColor, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<MaterialStateProperty<Color?>>('rangeSelectionOverlayColor', rangeSelectionOverlayColor, defaultValue: null));
|
||||
properties.add(ColorProperty('dividerColor', dividerColor, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<InputDecorationTheme>('inputDecorationTheme', inputDecorationTheme, defaultValue: null));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
import 'date.dart';
|
||||
import 'date_picker_theme.dart';
|
||||
import 'input_border.dart';
|
||||
import 'input_decorator.dart';
|
||||
import 'material_localizations.dart';
|
||||
@ -248,16 +249,19 @@ class _InputDatePickerFormFieldState extends State<InputDatePickerFormField> {
|
||||
final ThemeData theme = Theme.of(context);
|
||||
final bool useMaterial3 = theme.useMaterial3;
|
||||
final MaterialLocalizations localizations = MaterialLocalizations.of(context);
|
||||
final DatePickerThemeData datePickerTheme = theme.datePickerTheme;
|
||||
final InputDecorationTheme inputTheme = theme.inputDecorationTheme;
|
||||
final InputBorder inputBorder = inputTheme.border
|
||||
final InputBorder effectiveInputBorder = datePickerTheme.inputDecorationTheme?.border
|
||||
?? theme.inputDecorationTheme.border
|
||||
?? (useMaterial3 ? const OutlineInputBorder() : const UnderlineInputBorder());
|
||||
|
||||
return TextFormField(
|
||||
decoration: InputDecoration(
|
||||
border: inputBorder,
|
||||
filled: inputTheme.filled,
|
||||
hintText: widget.fieldHintText ?? localizations.dateHelpText,
|
||||
labelText: widget.fieldLabelText ?? localizations.dateInputLabel,
|
||||
).applyDefaults(inputTheme
|
||||
.merge(datePickerTheme.inputDecorationTheme)
|
||||
.copyWith(border: effectiveInputBorder),
|
||||
),
|
||||
validator: _validateDate,
|
||||
keyboardType: widget.keyboardType ?? TextInputType.datetime,
|
||||
|
@ -40,7 +40,11 @@ void main() {
|
||||
rangePickerHeaderHelpStyle: TextStyle(fontSize: 15),
|
||||
rangeSelectionBackgroundColor: Color(0xffffff2f),
|
||||
rangeSelectionOverlayColor: MaterialStatePropertyAll<Color>(Color(0xffffff3f)),
|
||||
dividerColor: Color(0xffffff3f),
|
||||
dividerColor: Color(0xffffff4f),
|
||||
inputDecorationTheme: InputDecorationTheme(
|
||||
fillColor: Color(0xffffff5f),
|
||||
border: UnderlineInputBorder(),
|
||||
)
|
||||
);
|
||||
|
||||
Material findDialogMaterial(WidgetTester tester) {
|
||||
@ -119,6 +123,7 @@ void main() {
|
||||
expect(theme.rangeSelectionBackgroundColor, null);
|
||||
expect(theme.rangeSelectionOverlayColor, null);
|
||||
expect(theme.dividerColor, null);
|
||||
expect(theme.inputDecorationTheme, null);
|
||||
});
|
||||
|
||||
testWidgets('DatePickerTheme.defaults M3 defaults', (WidgetTester tester) async {
|
||||
@ -129,7 +134,7 @@ void main() {
|
||||
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeData.light(useMaterial3: true),
|
||||
theme: ThemeData(useMaterial3: true),
|
||||
home: Builder(
|
||||
builder: (BuildContext context) {
|
||||
m3 = DatePickerTheme.defaults(context);
|
||||
@ -193,6 +198,7 @@ void main() {
|
||||
expect(m3.rangePickerHeaderHeadlineStyle, textTheme.titleLarge);
|
||||
expect(m3.rangePickerHeaderHelpStyle, textTheme.titleSmall);
|
||||
expect(m3.dividerColor, null);
|
||||
expect(m3.inputDecorationTheme, null);
|
||||
});
|
||||
|
||||
testWidgets('DatePickerTheme.defaults M2 defaults', (WidgetTester tester) async {
|
||||
@ -203,7 +209,7 @@ void main() {
|
||||
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeData.light(useMaterial3: false),
|
||||
theme: ThemeData(useMaterial3: false),
|
||||
home: Builder(
|
||||
builder: (BuildContext context) {
|
||||
m2 = DatePickerTheme.defaults(context);
|
||||
@ -258,6 +264,8 @@ void main() {
|
||||
expect(m2.rangePickerHeaderForegroundColor, colorScheme.onPrimary);
|
||||
expect(m2.rangePickerHeaderHeadlineStyle, textTheme.headlineSmall);
|
||||
expect(m2.rangePickerHeaderHelpStyle, textTheme.labelSmall);
|
||||
expect(m2.dividerColor, null);
|
||||
expect(m2.inputDecorationTheme, null);
|
||||
});
|
||||
|
||||
testWidgets('Default DatePickerThemeData debugFillProperties', (WidgetTester tester) async {
|
||||
@ -282,7 +290,9 @@ void main() {
|
||||
.map((DiagnosticsNode node) => node.toString())
|
||||
.toList();
|
||||
|
||||
expect(description, <String>[
|
||||
expect(
|
||||
description,
|
||||
equalsIgnoringHashCodes(<String>[
|
||||
'backgroundColor: Color(0xfffffff0)',
|
||||
'elevation: 6.0',
|
||||
'shadowColor: Color(0xfffffff1)',
|
||||
@ -315,15 +325,18 @@ void main() {
|
||||
'rangePickerHeaderHelpStyle: TextStyle(inherit: true, size: 15.0)',
|
||||
'rangeSelectionBackgroundColor: Color(0xffffff2f)',
|
||||
'rangeSelectionOverlayColor: MaterialStatePropertyAll(Color(0xffffff3f))',
|
||||
'dividerColor: Color(0xffffff3f)',
|
||||
]);
|
||||
'dividerColor: Color(0xffffff4f)',
|
||||
'inputDecorationTheme: InputDecorationTheme#00000(fillColor: Color(0xffffff5f), border: UnderlineInputBorder())'
|
||||
]),
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('DatePickerDialog uses ThemeData datePicker theme', (WidgetTester tester) async {
|
||||
testWidgets('DatePickerDialog uses ThemeData datePicker theme (calendar mode)', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeData.light(useMaterial3: true).copyWith(
|
||||
theme: ThemeData(
|
||||
datePickerTheme: datePickerTheme,
|
||||
useMaterial3: true,
|
||||
),
|
||||
home: Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
@ -398,11 +411,53 @@ void main() {
|
||||
expect(year2023Decoration.border?.bottom.color, datePickerTheme.todayForegroundColor?.resolve(<MaterialState>{}));
|
||||
});
|
||||
|
||||
testWidgets('DatePickerDialog uses ThemeData datePicker theme (input mode)', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeData(
|
||||
datePickerTheme: datePickerTheme,
|
||||
useMaterial3: true,
|
||||
),
|
||||
home: Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: Material(
|
||||
child: Center(
|
||||
child: DatePickerDialog(
|
||||
initialEntryMode: DatePickerEntryMode.input,
|
||||
initialDate: DateTime(2023, DateTime.january, 25),
|
||||
firstDate: DateTime(2022),
|
||||
lastDate: DateTime(2024, DateTime.december, 31),
|
||||
currentDate: DateTime(2023, DateTime.january, 24),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
final Material material = findDialogMaterial(tester);
|
||||
expect(material.color, datePickerTheme.backgroundColor);
|
||||
expect(material.elevation, datePickerTheme.elevation);
|
||||
expect(material.shadowColor, datePickerTheme.shadowColor);
|
||||
expect(material.surfaceTintColor, datePickerTheme.surfaceTintColor);
|
||||
expect(material.shape, datePickerTheme.shape);
|
||||
|
||||
final Text selectDate = tester.widget<Text>(find.text('Select date'));
|
||||
final Material headerMaterial = findHeaderMaterial(tester, 'Select date');
|
||||
expect(selectDate.style?.color, datePickerTheme.headerForegroundColor);
|
||||
expect(selectDate.style?.fontSize, datePickerTheme.headerHelpStyle?.fontSize);
|
||||
expect(headerMaterial.color, datePickerTheme.headerBackgroundColor);
|
||||
|
||||
final InputDecoration inputDecoration = tester.widget<TextField>(find.byType(TextField)).decoration!;
|
||||
expect(inputDecoration.fillColor, datePickerTheme.inputDecorationTheme?.fillColor);
|
||||
});
|
||||
|
||||
testWidgets('DateRangePickerDialog uses ThemeData datePicker theme', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeData.light(useMaterial3: true).copyWith(
|
||||
theme: ThemeData(
|
||||
datePickerTheme: datePickerTheme,
|
||||
useMaterial3: true,
|
||||
),
|
||||
home: Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
@ -450,8 +505,9 @@ void main() {
|
||||
addTearDown(tester.view.reset);
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeData.light(useMaterial3: true).copyWith(
|
||||
theme: ThemeData(
|
||||
datePickerTheme: datePickerTheme,
|
||||
useMaterial3: true,
|
||||
),
|
||||
home: Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
@ -482,4 +538,60 @@ void main() {
|
||||
final Divider horizontalDivider = tester.widget(find.byType(Divider));
|
||||
expect(horizontalDivider.color, datePickerTheme.dividerColor);
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
'DatePicker uses ThemeData.inputDecorationTheme properties '
|
||||
'which are null in DatePickerThemeData.inputDecorationTheme',
|
||||
(WidgetTester tester) async {
|
||||
|
||||
Widget buildWidget({
|
||||
InputDecorationTheme? inputDecorationTheme,
|
||||
DatePickerThemeData? datePickerTheme,
|
||||
}) {
|
||||
return MaterialApp(
|
||||
theme: ThemeData(
|
||||
useMaterial3: true,
|
||||
inputDecorationTheme: inputDecorationTheme,
|
||||
datePickerTheme: datePickerTheme,
|
||||
),
|
||||
home: Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: Material(
|
||||
child: Center(
|
||||
child: DatePickerDialog(
|
||||
initialEntryMode: DatePickerEntryMode.input,
|
||||
initialDate: DateTime(2023, DateTime.january, 25),
|
||||
firstDate: DateTime(2022),
|
||||
lastDate: DateTime(2024, DateTime.december, 31),
|
||||
currentDate: DateTime(2023, DateTime.january, 24),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Test DatePicker with DatePickerThemeData.inputDecorationTheme.
|
||||
await tester.pumpWidget(buildWidget(
|
||||
inputDecorationTheme: const InputDecorationTheme(filled: true),
|
||||
datePickerTheme: datePickerTheme,
|
||||
));
|
||||
InputDecoration inputDecoration = tester.widget<TextField>(find.byType(TextField)).decoration!;
|
||||
expect(inputDecoration.fillColor, datePickerTheme.inputDecorationTheme!.fillColor);
|
||||
expect(inputDecoration.border , datePickerTheme.inputDecorationTheme!.border);
|
||||
|
||||
// Test DatePicker with ThemeData.inputDecorationTheme.
|
||||
await tester.pumpWidget(buildWidget(
|
||||
inputDecorationTheme: const InputDecorationTheme(
|
||||
filled: true,
|
||||
fillColor: Color(0xFF00FF00),
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
inputDecoration = tester.widget<TextField>(find.byType(TextField)).decoration!;
|
||||
expect(inputDecoration.fillColor, const Color(0xFF00FF00));
|
||||
expect(inputDecoration.border , const OutlineInputBorder());
|
||||
});
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user