Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
198a51ac
Unverified
Commit
198a51ac
authored
Jan 31, 2023
by
Hans Muller
Committed by
GitHub
Jan 31, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Migrate the Material Date pickers to M3 Reprise (#119033)
parent
38843814
Changes
11
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
1934 additions
and
158 deletions
+1934
-158
gen_defaults.dart
dev/tools/gen_defaults/bin/gen_defaults.dart
+2
-0
date_picker_template.dart
dev/tools/gen_defaults/lib/date_picker_template.dart
+238
-0
material.dart
packages/flutter/lib/material.dart
+1
-0
calendar_date_picker.dart
packages/flutter/lib/src/material/calendar_date_picker.dart
+88
-68
date_picker.dart
packages/flutter/lib/src/material/date_picker.dart
+169
-88
date_picker_theme.dart
packages/flutter/lib/src/material/date_picker_theme.dart
+975
-0
input_date_picker_form_field.dart
...lutter/lib/src/material/input_date_picker_form_field.dart
+7
-2
material.dart
packages/flutter/lib/src/material/material.dart
+6
-0
theme_data.dart
packages/flutter/lib/src/material/theme_data.dart
+17
-0
date_picker_theme_test.dart
packages/flutter/test/material/date_picker_theme_test.dart
+426
-0
theme_data_test.dart
packages/flutter/test/material/theme_data_test.dart
+5
-0
No files found.
dev/tools/gen_defaults/bin/gen_defaults.dart
View file @
198a51ac
...
...
@@ -27,6 +27,7 @@ import 'package:gen_defaults/button_template.dart';
import
'package:gen_defaults/card_template.dart'
;
import
'package:gen_defaults/checkbox_template.dart'
;
import
'package:gen_defaults/color_scheme_template.dart'
;
import
'package:gen_defaults/date_picker_template.dart'
;
import
'package:gen_defaults/dialog_template.dart'
;
import
'package:gen_defaults/divider_template.dart'
;
import
'package:gen_defaults/drawer_template.dart'
;
...
...
@@ -147,6 +148,7 @@ Future<void> main(List<String> args) async {
CardTemplate
(
'Card'
,
'
$materialLib
/card.dart'
,
tokens
).
updateFile
();
CheckboxTemplate
(
'Checkbox'
,
'
$materialLib
/checkbox.dart'
,
tokens
).
updateFile
();
ColorSchemeTemplate
(
'ColorScheme'
,
'
$materialLib
/theme_data.dart'
,
tokens
).
updateFile
();
DatePickerTemplate
(
'DatePicker'
,
'
$materialLib
/date_picker_theme.dart'
,
tokens
).
updateFile
();
DialogFullscreenTemplate
(
'DialogFullscreen'
,
'
$materialLib
/dialog.dart'
,
tokens
).
updateFile
();
DialogTemplate
(
'Dialog'
,
'
$materialLib
/dialog.dart'
,
tokens
).
updateFile
();
DividerTemplate
(
'Divider'
,
'
$materialLib
/divider.dart'
,
tokens
).
updateFile
();
...
...
dev/tools/gen_defaults/lib/date_picker_template.dart
0 → 100644
View file @
198a51ac
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'template.dart'
;
class
DatePickerTemplate
extends
TokenTemplate
{
const
DatePickerTemplate
(
super
.
blockName
,
super
.
fileName
,
super
.
tokens
,
{
super
.
colorSchemePrefix
=
'_colors.'
,
super
.
textThemePrefix
=
'_textTheme.'
});
String
_layerOpacity
(
String
layerToken
)
{
if
(
tokens
.
containsKey
(
layerToken
))
{
final
String
?
layerValue
=
tokens
[
layerToken
]
as
String
?;
if
(
tokens
.
containsKey
(
layerValue
))
{
final
String
?
opacityValue
=
opacity
(
layerValue
!);
if
(
opacityValue
!=
null
)
{
return
'.withOpacity(
$opacityValue
)'
;
}
}
}
return
''
;
}
String
_stateColor
(
String
componentToken
,
String
?
type
,
String
state
)
{
final
String
baseColor
=
color
(
type
!=
null
?
'
$componentToken
.
$type
.
$state
.state-layer.color'
:
'
$componentToken
.
$state
.state-layer.color'
,
''
);
if
(
baseColor
.
isEmpty
)
{
return
'null'
;
}
final
String
opacity
=
_layerOpacity
(
'
$componentToken
.
$state
.state-layer.opacity'
);
return
'
$baseColor$opacity
'
;
}
@override
String
generate
()
=>
'''
class _
${blockName}
DefaultsM3 extends DatePickerThemeData {
_
${blockName}
DefaultsM3(this.context)
: super(
elevation:
${elevation("md.comp.date-picker.modal.container")}
,
shape:
${shape("md.comp.date-picker.modal.container")}
,
rangePickerElevation:
${elevation("md.comp.date-picker.modal.range-selection.container")}
,
rangePickerShape:
${shape("md.comp.date-picker.modal.range-selection.container")}
,
);
final BuildContext context;
late final ThemeData _theme = Theme.of(context);
late final ColorScheme _colors = _theme.colorScheme;
late final TextTheme _textTheme = _theme.textTheme;
@override
Color? get backgroundColor =>
${componentColor("md.comp.date-picker.modal.container")}
;
@override
Color? get shadowColor =>
${colorOrTransparent("md.comp.date-picker.modal.container.shadow-color")}
;
@override
Color? get surfaceTintColor =>
${colorOrTransparent("md.comp.date-picker.modal.container.surface-tint-layer.color")}
;
@override
Color? get headerBackgroundColor =>
${colorOrTransparent("md.comp.date-picker.modal.header.container.color")}
;
@override
Color? get headerForegroundColor =>
${colorOrTransparent("md.comp.date-picker.modal.header.headline.color")}
;
@override
TextStyle? get headerHeadlineStyle =>
${textStyle("md.comp.date-picker.modal.header.headline")}
;
@override
TextStyle? get headerHelpStyle =>
${textStyle("md.comp.date-picker.modal.header.supporting-text")}
;
@override
TextStyle? get weekdayStyle =>
${textStyle("md.comp.date-picker.modal.weekdays.label-text")}
?.apply(
color:
${componentColor("md.comp.date-picker.modal.weekdays.label-text")}
,
);
@override
TextStyle? get dayStyle =>
${textStyle("md.comp.date-picker.modal.date.label-text")}
;
@override
MaterialStateProperty<Color?>? get dayForegroundColor =>
MaterialStateProperty.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.selected)) {
return
${componentColor('md.comp.date-picker.modal.date.selected.label-text')}
;
} else if (states.contains(MaterialState.disabled)) {
return
${componentColor('md.comp.date-picker.modal.date.unselected.label-text')}
.withOpacity(0.38);
}
return
${componentColor('md.comp.date-picker.modal.date.unselected.label-text')}
;
});
@override
MaterialStateProperty<Color?>? get dayBackgroundColor =>
MaterialStateProperty.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.selected)) {
return
${componentColor('md.comp.date-picker.modal.date.selected.container')}
;
}
return
${componentColor('md.comp.date-picker.modal.date.unselected.container')}
;
});
@override
MaterialStateProperty<Color?>? get dayOverlayColor =>
MaterialStateProperty.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.selected)) {
if (states.contains(MaterialState.hovered)) {
return
${_stateColor('md.comp.date-picker.modal.date', 'selected', 'hover')}
;
}
if (states.contains(MaterialState.focused)) {
return
${_stateColor('md.comp.date-picker.modal.date', 'selected', 'focus')}
;
}
if (states.contains(MaterialState.pressed)) {
return
${_stateColor('md.comp.date-picker.modal.date', 'selected', 'pressed')}
;
}
} else {
if (states.contains(MaterialState.hovered)) {
return
${_stateColor('md.comp.date-picker.modal.date', 'unselected', 'hover')}
;
}
if (states.contains(MaterialState.focused)) {
return
${_stateColor('md.comp.date-picker.modal.date', 'unselected', 'focus')}
;
}
if (states.contains(MaterialState.pressed)) {
return
${_stateColor('md.comp.date-picker.modal.date', 'unselected', 'pressed')}
;
}
}
return null;
});
@override
MaterialStateProperty<Color?>? get todayForegroundColor =>
MaterialStateProperty.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.selected)) {
return
${componentColor('md.comp.date-picker.modal.date.selected.label-text')}
;
} else if (states.contains(MaterialState.disabled)) {
return
${componentColor('md.comp.date-picker.modal.date.today.label-text')}
.withOpacity(0.38);
}
return
${componentColor('md.comp.date-picker.modal.date.today.label-text')}
;
});
@override
MaterialStateProperty<Color?>? get todayBackgroundColor => dayBackgroundColor;
@override
BorderSide? get todayBorder =>
${border('md.comp.date-picker.modal.date.today.container.outline')}
;
@override
TextStyle? get yearStyle =>
${textStyle("md.comp.date-picker.modal.year-selection.year.label-text")}
;
@override
MaterialStateProperty<Color?>? get yearForegroundColor =>
MaterialStateProperty.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.selected)) {
return
${componentColor('md.comp.date-picker.modal.year-selection.year.selected.label-text')}
;
} else if (states.contains(MaterialState.disabled)) {
return
${componentColor('md.comp.date-picker.modal.year-selection.year.unselected.label-text')}
.withOpacity(0.38);
}
return
${componentColor('md.comp.date-picker.modal.year-selection.year.unselected.label-text')}
;
});
@override
MaterialStateProperty<Color?>? get yearBackgroundColor =>
MaterialStateProperty.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.selected)) {
return
${componentColor('md.comp.date-picker.modal.year-selection.year.selected.container')}
;
}
return
${componentColor('md.comp.date-picker.modal.year-selection.year.unselected.container')}
;
});
@override
MaterialStateProperty<Color?>? get yearOverlayColor =>
MaterialStateProperty.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.selected)) {
if (states.contains(MaterialState.hovered)) {
return
${_stateColor('md.comp.date-picker.modal.year-selection.year', 'selected', 'hover')}
;
}
if (states.contains(MaterialState.focused)) {
return
${_stateColor('md.comp.date-picker.modal.year-selection.year', 'selected', 'focus')}
;
}
if (states.contains(MaterialState.pressed)) {
return
${_stateColor('md.comp.date-picker.modal.year-selection.year', 'selected', 'pressed')}
;
}
} else {
if (states.contains(MaterialState.hovered)) {
return
${_stateColor('md.comp.date-picker.modal.year-selection.year', 'unselected', 'hover')}
;
}
if (states.contains(MaterialState.focused)) {
return
${_stateColor('md.comp.date-picker.modal.year-selection.year', 'unselected', 'focus')}
;
}
if (states.contains(MaterialState.pressed)) {
return
${_stateColor('md.comp.date-picker.modal.year-selection.year', 'unselected', 'pressed')}
;
}
}
return null;
});
@override
Color? get rangePickerShadowColor =>
${colorOrTransparent("md.comp.date-picker.modal.range-selection.container.shadow-color")}
;
@override
Color? get rangePickerSurfaceTintColor =>
${colorOrTransparent("md.comp.date-picker.modal.range-selection.container.surface-tint-layer.color")}
;
@override
Color? get rangeSelectionBackgroundColor =>
${colorOrTransparent("md.comp.date-picker.modal.range-selection.active-indicator.container.color")}
;
@override
MaterialStateProperty<Color?>? get rangeSelectionOverlayColor =>
MaterialStateProperty.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.hovered)) {
return
${_stateColor('md.comp.date-picker.modal.range-selection.date.in-range.', null, 'hover')}
;
}
if (states.contains(MaterialState.focused)) {
return
${_stateColor('md.comp.date-picker.modal.range-selection.date.in-range.', null, 'focus')}
;
}
if (states.contains(MaterialState.pressed)) {
return
${_stateColor('md.comp.date-picker.modal.range-selection.date.in-range.', null, 'pressed')}
;
}
return null;
});
@override
Color? get rangePickerHeaderBackgroundColor =>
${colorOrTransparent("md.comp.date-picker.modal.header.container.color")}
;
@override
Color? get rangePickerHeaderForegroundColor =>
${colorOrTransparent("md.comp.date-picker.modal.header.headline.color")}
;
@override
TextStyle? get rangePickerHeaderHeadlineStyle =>
${textStyle("md.comp.date-picker.modal.range-selection.header.headline")}
;
@override
TextStyle? get rangePickerHeaderHelpStyle =>
${textStyle("md.comp.date-picker.modal.range-selection.month.subhead")}
;
}
'''
;
}
packages/flutter/lib/material.dart
View file @
198a51ac
...
...
@@ -65,6 +65,7 @@ export 'src/material/data_table_source.dart';
export
'src/material/data_table_theme.dart'
;
export
'src/material/date.dart'
;
export
'src/material/date_picker.dart'
;
export
'src/material/date_picker_theme.dart'
;
export
'src/material/debug.dart'
;
export
'src/material/desktop_text_selection.dart'
;
export
'src/material/desktop_text_selection_toolbar.dart'
;
...
...
packages/flutter/lib/src/material/calendar_date_picker.dart
View file @
198a51ac
...
...
@@ -11,12 +11,14 @@ import 'package:flutter/widgets.dart';
import
'color_scheme.dart'
;
import
'date.dart'
;
import
'date_picker_theme.dart'
;
import
'debug.dart'
;
import
'divider.dart'
;
import
'icon_button.dart'
;
import
'icons.dart'
;
import
'ink_well.dart'
;
import
'material_localizations.dart'
;
import
'material_state.dart'
;
import
'text_theme.dart'
;
import
'theme.dart'
;
...
...
@@ -279,7 +281,7 @@ class _CalendarDatePickerState extends State<CalendarDatePicker> {
firstDate:
widget
.
firstDate
,
lastDate:
widget
.
lastDate
,
initialDate:
_currentDisplayedMonthDate
,
selectedDate:
_
selected
Date
,
selectedDate:
_
currentDisplayedMonth
Date
,
onChanged:
_handleYearChanged
,
),
);
...
...
@@ -920,18 +922,11 @@ class _DayPickerState extends State<_DayPicker> {
@override
Widget
build
(
BuildContext
context
)
{
final
ColorScheme
colorScheme
=
Theme
.
of
(
context
).
colorScheme
;
final
MaterialLocalizations
localizations
=
MaterialLocalizations
.
of
(
context
);
final
TextTheme
textTheme
=
Theme
.
of
(
context
).
textTheme
;
final
TextStyle
?
headerStyle
=
textTheme
.
bodySmall
?.
apply
(
color:
colorScheme
.
onSurface
.
withOpacity
(
0.60
),
);
final
TextStyle
dayStyle
=
textTheme
.
bodySmall
!;
final
Color
enabledDayColor
=
colorScheme
.
onSurface
.
withOpacity
(
0.87
);
final
Color
disabledDayColor
=
colorScheme
.
onSurface
.
withOpacity
(
0.38
);
final
Color
selectedDayColor
=
colorScheme
.
onPrimary
;
final
Color
selectedDayBackground
=
colorScheme
.
primary
;
final
Color
todayColor
=
colorScheme
.
primary
;
final
DatePickerThemeData
datePickerTheme
=
DatePickerTheme
.
of
(
context
);
final
DatePickerThemeData
defaults
=
DatePickerTheme
.
defaults
(
context
);
final
TextStyle
?
weekdayStyle
=
datePickerTheme
.
weekdayStyle
??
defaults
.
weekdayStyle
;
final
TextStyle
?
dayStyle
=
datePickerTheme
.
dayStyle
??
defaults
.
dayStyle
;
final
int
year
=
widget
.
displayedMonth
.
year
;
final
int
month
=
widget
.
displayedMonth
.
month
;
...
...
@@ -939,7 +934,19 @@ class _DayPickerState extends State<_DayPicker> {
final
int
daysInMonth
=
DateUtils
.
getDaysInMonth
(
year
,
month
);
final
int
dayOffset
=
DateUtils
.
firstDayOffset
(
year
,
month
,
localizations
);
final
List
<
Widget
>
dayItems
=
_dayHeaders
(
headerStyle
,
localizations
);
T
?
effectiveValue
<
T
>(
T
?
Function
(
DatePickerThemeData
?
theme
)
getProperty
)
{
return
getProperty
(
datePickerTheme
)
??
getProperty
(
defaults
);
}
T
?
resolve
<
T
>(
MaterialStateProperty
<
T
>?
Function
(
DatePickerThemeData
?
theme
)
getProperty
,
Set
<
MaterialState
>
states
)
{
return
effectiveValue
(
(
DatePickerThemeData
?
theme
)
{
return
getProperty
(
theme
)?.
resolve
(
states
);
},
);
}
final
List
<
Widget
>
dayItems
=
_dayHeaders
(
weekdayStyle
,
localizations
);
// 1-based day of month, e.g. 1-31 for January, and 1-29 for February on
// a leap year.
int
day
=
-
dayOffset
;
...
...
@@ -949,43 +956,42 @@ class _DayPickerState extends State<_DayPicker> {
dayItems
.
add
(
Container
());
}
else
{
final
DateTime
dayToBuild
=
DateTime
(
year
,
month
,
day
);
final
bool
isDisabled
=
dayToBuild
.
isAfter
(
widget
.
lastDate
)
||
final
bool
isDisabled
=
dayToBuild
.
isAfter
(
widget
.
lastDate
)
||
dayToBuild
.
isBefore
(
widget
.
firstDate
)
||
(
widget
.
selectableDayPredicate
!=
null
&&
!
widget
.
selectableDayPredicate
!(
dayToBuild
));
final
bool
isSelectedDay
=
DateUtils
.
isSameDay
(
widget
.
selectedDate
,
dayToBuild
);
final
bool
isToday
=
DateUtils
.
isSameDay
(
widget
.
currentDate
,
dayToBuild
);
final
String
semanticLabelSuffix
=
isToday
?
',
${localizations.currentDateLabel}
'
:
''
;
BoxDecoration
?
decoration
;
Color
dayColor
=
enabledDayColor
;
if
(
isSelectedDay
)
{
// The selected day gets a circle background highlight, and a
// contrasting text color.
dayColor
=
selectedDayColor
;
decoration
=
BoxDecoration
(
color:
selectedDayBackground
,
shape:
BoxShape
.
circle
,
final
Set
<
MaterialState
>
states
=
<
MaterialState
>{
if
(
isDisabled
)
MaterialState
.
disabled
,
if
(
isSelectedDay
)
MaterialState
.
selected
,
};
final
Color
?
dayForegroundColor
=
resolve
<
Color
?>((
DatePickerThemeData
?
theme
)
=>
isToday
?
theme
?.
todayForegroundColor
:
theme
?.
dayForegroundColor
,
states
)
;
final
Color
?
dayBackgroundColor
=
resolve
<
Color
?>((
DatePickerThemeData
?
theme
)
=>
isToday
?
theme
?.
todayBackgroundColor
:
theme
?.
dayBackgroundColor
,
states
);
final
MaterialStateProperty
<
Color
?>
dayOverlayColor
=
MaterialStateProperty
.
resolveWith
<
Color
?>(
(
Set
<
MaterialState
>
states
)
=>
effectiveValue
((
DatePickerThemeData
?
theme
)
=>
theme
?.
dayOverlayColor
?.
resolve
(
states
))
,
);
}
else
if
(
isToday
)
{
// The current day gets a different text color (if enabled) and a circle stroke
// border.
if
(
isDisabled
)
{
dayColor
=
disabledDayColor
;
}
else
{
dayColor
=
todayColor
;
}
decoration
=
BoxDecoration
(
border:
Border
.
all
(
color:
dayColor
),
final
BoxDecoration
decoration
=
isToday
?
BoxDecoration
(
color:
dayBackgroundColor
,
border:
Border
.
fromBorderSide
(
(
datePickerTheme
.
todayBorder
??
defaults
.
todayBorder
!)
.
copyWith
(
color:
dayForegroundColor
)
),
shape:
BoxShape
.
circle
,
)
:
BoxDecoration
(
color:
dayBackgroundColor
,
shape:
BoxShape
.
circle
,
);
}
else
if
(
isDisabled
)
{
dayColor
=
disabledDayColor
;
}
Widget
dayWidget
=
Container
(
decoration:
decoration
,
child:
Center
(
child:
Text
(
localizations
.
formatDecimal
(
day
),
style:
dayStyle
.
apply
(
color:
day
Color
)),
child:
Text
(
localizations
.
formatDecimal
(
day
),
style:
dayStyle
?.
apply
(
color:
dayForeground
Color
)),
),
);
...
...
@@ -998,7 +1004,8 @@ class _DayPickerState extends State<_DayPicker> {
focusNode:
_dayFocusNodes
[
day
-
1
],
onTap:
()
=>
widget
.
onChanged
(
dayToBuild
),
radius:
_dayPickerRowHeight
/
2
+
4
,
splashColor:
selectedDayBackground
.
withOpacity
(
0.38
),
statesController:
MaterialStatesController
(
states
),
overlayColor:
dayOverlayColor
,
child:
Semantics
(
// We want the day of month to be spoken first irrespective of the
// locale-specific preferences or TextDirection. This is because
...
...
@@ -1150,8 +1157,20 @@ class _YearPickerState extends State<YearPicker> {
}
Widget
_buildYearItem
(
BuildContext
context
,
int
index
)
{
final
ColorScheme
colorScheme
=
Theme
.
of
(
context
).
colorScheme
;
final
TextTheme
textTheme
=
Theme
.
of
(
context
).
textTheme
;
final
DatePickerThemeData
datePickerTheme
=
DatePickerTheme
.
of
(
context
);
final
DatePickerThemeData
defaults
=
DatePickerTheme
.
defaults
(
context
);
T
?
effectiveValue
<
T
>(
T
?
Function
(
DatePickerThemeData
?
theme
)
getProperty
)
{
return
getProperty
(
datePickerTheme
)
??
getProperty
(
defaults
);
}
T
?
resolve
<
T
>(
MaterialStateProperty
<
T
>?
Function
(
DatePickerThemeData
?
theme
)
getProperty
,
Set
<
MaterialState
>
states
)
{
return
effectiveValue
(
(
DatePickerThemeData
?
theme
)
{
return
getProperty
(
theme
)?.
resolve
(
states
);
},
);
}
// Backfill the _YearPicker with disabled years if necessary.
final
int
offset
=
_itemCount
<
minYears
?
(
minYears
-
_itemCount
)
~/
2
:
0
;
...
...
@@ -1162,33 +1181,32 @@ class _YearPickerState extends State<YearPicker> {
const
double
decorationHeight
=
36.0
;
const
double
decorationWidth
=
72.0
;
final
Color
textColor
;
if
(
isSelected
)
{
textColor
=
colorScheme
.
onPrimary
;
}
else
if
(
isDisabled
)
{
textColor
=
colorScheme
.
onSurface
.
withOpacity
(
0.38
);
}
else
if
(
isCurrentYear
)
{
textColor
=
colorScheme
.
primary
;
}
else
{
textColor
=
colorScheme
.
onSurface
.
withOpacity
(
0.87
);
}
final
TextStyle
?
itemStyle
=
textTheme
.
bodyLarge
?.
apply
(
color:
textColor
);
final
Set
<
MaterialState
>
states
=
<
MaterialState
>{
if
(
isDisabled
)
MaterialState
.
disabled
,
if
(
isSelected
)
MaterialState
.
selected
,
};
BoxDecoration
?
decoration
;
if
(
isSelected
)
{
decoration
=
BoxDecoration
(
color:
colorScheme
.
primary
,
borderRadius:
BorderRadius
.
circular
(
decorationHeight
/
2
),
final
Color
?
textColor
=
resolve
<
Color
?>((
DatePickerThemeData
?
theme
)
=>
isCurrentYear
?
theme
?.
todayForegroundColor
:
theme
?.
yearForegroundColor
,
states
)
;
final
Color
?
background
=
resolve
<
Color
?>((
DatePickerThemeData
?
theme
)
=>
isCurrentYear
?
theme
?.
todayBackgroundColor
:
theme
?.
yearBackgroundColor
,
states
);
final
MaterialStateProperty
<
Color
?>
overlayColor
=
MaterialStateProperty
.
resolveWith
<
Color
?>((
Set
<
MaterialState
>
states
)
=>
effectiveValue
((
DatePickerThemeData
?
theme
)
=>
theme
?.
dayOverlayColor
?.
resolve
(
states
)
),
);
}
else
if
(
isCurrentYear
&&
!
isDisabled
)
{
decoration
=
BoxDecoration
(
border:
Border
.
all
(
color:
colorScheme
.
primary
,
),
BoxBorder
?
border
;
if
(
isCurrentYear
)
{
final
BorderSide
?
todayBorder
=
datePickerTheme
.
todayBorder
??
defaults
.
todayBorder
;
if
(
todayBorder
!=
null
)
{
border
=
Border
.
fromBorderSide
(
todayBorder
.
copyWith
(
color:
textColor
));
}
}
final
BoxDecoration
decoration
=
BoxDecoration
(
border:
border
,
color:
background
,
borderRadius:
BorderRadius
.
circular
(
decorationHeight
/
2
),
);
}
final
TextStyle
?
itemStyle
=
(
datePickerTheme
.
yearStyle
??
defaults
.
yearStyle
)?.
apply
(
color:
textColor
);
Widget
yearItem
=
Center
(
child:
Container
(
decoration:
decoration
,
...
...
@@ -1212,6 +1230,8 @@ class _YearPickerState extends State<YearPicker> {
yearItem
=
InkWell
(
key:
ValueKey
<
int
>(
year
),
onTap:
()
=>
widget
.
onChanged
(
DateTime
(
year
,
widget
.
initialDate
.
month
)),
statesController:
MaterialStatesController
(
states
),
overlayColor:
overlayColor
,
child:
yearItem
,
);
}
...
...
packages/flutter/lib/src/material/date_picker.dart
View file @
198a51ac
...
...
@@ -10,9 +10,12 @@ import 'package:flutter/widgets.dart';
import
'app_bar.dart'
;
import
'back_button.dart'
;
import
'button_style.dart'
;
import
'calendar_date_picker.dart'
;
import
'color_scheme.dart'
;
import
'colors.dart'
;
import
'date.dart'
;
import
'date_picker_theme.dart'
;
import
'debug.dart'
;
import
'dialog.dart'
;
import
'dialog_theme.dart'
;
...
...
@@ -25,15 +28,20 @@ import 'input_date_picker_form_field.dart';
import
'input_decorator.dart'
;
import
'material.dart'
;
import
'material_localizations.dart'
;
import
'material_state.dart'
;
import
'scaffold.dart'
;
import
'text_button.dart'
;
import
'text_field.dart'
;
import
'text_theme.dart'
;
import
'theme.dart'
;
const
Size
_calendarPortraitDialogSize
=
Size
(
330.0
,
518.0
);
// The M3 sizes are coming from the tokens, but are hand coded,
// as the current token DB does not contain landscape versions.
const
Size
_calendarPortraitDialogSizeM2
=
Size
(
330.0
,
518.0
);
const
Size
_calendarPortraitDialogSizeM3
=
Size
(
328.0
,
512.0
);
const
Size
_calendarLandscapeDialogSize
=
Size
(
496.0
,
346.0
);
const
Size
_inputPortraitDialogSize
=
Size
(
330.0
,
270.0
);
const
Size
_inputPortraitDialogSizeM2
=
Size
(
330.0
,
270.0
);
const
Size
_inputPortraitDialogSizeM3
=
Size
(
328.0
,
270.0
);
const
Size
_inputLandscapeDialogSize
=
Size
(
496
,
160.0
);
const
Size
_inputRangeLandscapeDialogSize
=
Size
(
496
,
164.0
);
const
Duration
_dialogSizeAnimationDuration
=
Duration
(
milliseconds:
200
);
...
...
@@ -412,13 +420,15 @@ class _DatePickerDialogState extends State<DatePickerDialog> with RestorationMix
}
Size
_dialogSize
(
BuildContext
context
)
{
final
bool
useMaterial3
=
Theme
.
of
(
context
).
useMaterial3
;
final
Orientation
orientation
=
MediaQuery
.
orientationOf
(
context
);
switch
(
_entryMode
.
value
)
{
case
DatePickerEntryMode
.
calendar
:
case
DatePickerEntryMode
.
calendarOnly
:
switch
(
orientation
)
{
case
Orientation
.
portrait
:
return
_calendarPortraitDialogSize
;
return
useMaterial3
?
_calendarPortraitDialogSizeM3
:
_calendarPortraitDialogSizeM2
;
case
Orientation
.
landscape
:
return
_calendarLandscapeDialogSize
;
}
...
...
@@ -426,7 +436,7 @@ class _DatePickerDialogState extends State<DatePickerDialog> with RestorationMix
case
DatePickerEntryMode
.
inputOnly
:
switch
(
orientation
)
{
case
Orientation
.
portrait
:
return
_inputPortraitDialogSize
;
return
useMaterial3
?
_inputPortraitDialogSizeM3
:
_inputPortraitDialogSizeM2
;
case
Orientation
.
landscape
:
return
_inputLandscapeDialogSize
;
}
...
...
@@ -441,21 +451,28 @@ class _DatePickerDialogState extends State<DatePickerDialog> with RestorationMix
@override
Widget
build
(
BuildContext
context
)
{
final
ThemeData
theme
=
Theme
.
of
(
context
);
final
ColorScheme
colorScheme
=
theme
.
colorScheme
;
final
bool
useMaterial3
=
theme
.
useMaterial3
;
final
MaterialLocalizations
localizations
=
MaterialLocalizations
.
of
(
context
);
final
Orientation
orientation
=
MediaQuery
.
orientationOf
(
context
);
final
DatePickerThemeData
datePickerTheme
=
DatePickerTheme
.
of
(
context
);
final
DatePickerThemeData
defaults
=
DatePickerTheme
.
defaults
(
context
);
final
TextTheme
textTheme
=
theme
.
textTheme
;
// Constrain the textScaleFactor to the largest supported value to prevent
// layout issues.
final
double
textScaleFactor
=
math
.
min
(
MediaQuery
.
textScaleFactorOf
(
context
),
1.3
);
final
Color
?
headerForegroundColor
=
datePickerTheme
.
headerForegroundColor
??
defaults
.
headerForegroundColor
;
final
TextStyle
?
headlineStyle
=
useMaterial3
?
(
datePickerTheme
.
headerHeadlineStyle
??
defaults
.
headerHeadlineStyle
)?.
copyWith
(
color:
headerForegroundColor
,
)
// Material2 has support for landscape and the current M3 spec doesn't
// address this layout, so handling it seperately here.
:
(
orientation
==
Orientation
.
landscape
?
textTheme
.
headlineSmall
?.
copyWith
(
color:
headerForegroundColor
)
:
textTheme
.
headlineMedium
?.
copyWith
(
color:
headerForegroundColor
));
final
String
dateText
=
localizations
.
formatMediumDate
(
_selectedDate
.
value
);
final
Color
onPrimarySurface
=
colorScheme
.
brightness
==
Brightness
.
light
?
colorScheme
.
onPrimary
:
colorScheme
.
onSurface
;
final
TextStyle
?
dateStyle
=
orientation
==
Orientation
.
landscape
?
textTheme
.
headlineSmall
?.
copyWith
(
color:
onPrimarySurface
)
:
textTheme
.
headlineMedium
?.
copyWith
(
color:
onPrimarySurface
);
final
Widget
actions
=
Container
(
alignment:
AlignmentDirectional
.
centerEnd
,
...
...
@@ -467,7 +484,7 @@ class _DatePickerDialogState extends State<DatePickerDialog> with RestorationMix
TextButton
(
onPressed:
_handleCancel
,
child:
Text
(
widget
.
cancelText
??
(
theme
.
useMaterial3
useMaterial3
?
localizations
.
cancelButtonLabel
:
localizations
.
cancelButtonLabel
.
toUpperCase
()
)),
...
...
@@ -533,8 +550,8 @@ class _DatePickerDialogState extends State<DatePickerDialog> with RestorationMix
case
DatePickerEntryMode
.
calendar
:
picker
=
calendarDatePicker
();
entryModeButton
=
IconButton
(
icon:
const
Icon
(
Icons
.
edit
),
color:
onPrimarySurface
,
icon:
Icon
(
useMaterial3
?
Icons
.
edit_outlined
:
Icons
.
edit
),
color:
headerForegroundColor
,
tooltip:
localizations
.
inputDateModeButtonLabel
,
onPressed:
_handleEntryModeToggle
,
);
...
...
@@ -549,7 +566,7 @@ class _DatePickerDialogState extends State<DatePickerDialog> with RestorationMix
picker
=
inputDatePicker
();
entryModeButton
=
IconButton
(
icon:
const
Icon
(
Icons
.
calendar_today
),
color:
onPrimarySurface
,
color:
headerForegroundColor
,
tooltip:
localizations
.
calendarModeButtonLabel
,
onPressed:
_handleEntryModeToggle
,
);
...
...
@@ -563,19 +580,29 @@ class _DatePickerDialogState extends State<DatePickerDialog> with RestorationMix
final
Widget
header
=
_DatePickerHeader
(
helpText:
widget
.
helpText
??
(
Theme
.
of
(
context
).
useMaterial3
useMaterial3
?
localizations
.
datePickerHelpText
:
localizations
.
datePickerHelpText
.
toUpperCase
()
),
titleText:
dateText
,
titleStyle:
dat
eStyle
,
titleStyle:
headlin
eStyle
,
orientation:
orientation
,
isShort:
orientation
==
Orientation
.
landscape
,
entryModeButton:
entryModeButton
,
);
final
Size
dialogSize
=
_dialogSize
(
context
)
*
textScaleFactor
;
final
DialogTheme
dialogTheme
=
theme
.
dialogTheme
;
return
Dialog
(
backgroundColor:
datePickerTheme
.
backgroundColor
??
defaults
.
backgroundColor
,
elevation:
useMaterial3
?
datePickerTheme
.
elevation
??
defaults
.
elevation
!
:
datePickerTheme
.
elevation
??
dialogTheme
.
elevation
??
24
,
shadowColor:
datePickerTheme
.
shadowColor
??
defaults
.
shadowColor
,
surfaceTintColor:
datePickerTheme
.
surfaceTintColor
??
defaults
.
surfaceTintColor
,
shape:
useMaterial3
?
datePickerTheme
.
shape
??
defaults
.
shape
:
datePickerTheme
.
shape
??
dialogTheme
.
shape
??
defaults
.
shape
,
insetPadding:
const
EdgeInsets
.
symmetric
(
horizontal:
16.0
,
vertical:
24.0
),
clipBehavior:
Clip
.
antiAlias
,
child:
AnimatedContainer
(
...
...
@@ -595,6 +622,7 @@ class _DatePickerDialogState extends State<DatePickerDialog> with RestorationMix
crossAxisAlignment:
CrossAxisAlignment
.
stretch
,
children:
<
Widget
>[
header
,
if
(
useMaterial3
)
const
Divider
(),
Expanded
(
child:
picker
),
actions
,
],
...
...
@@ -605,6 +633,7 @@ class _DatePickerDialogState extends State<DatePickerDialog> with RestorationMix
crossAxisAlignment:
CrossAxisAlignment
.
stretch
,
children:
<
Widget
>[
header
,
if
(
useMaterial3
)
const
VerticalDivider
(),
Flexible
(
child:
Column
(
mainAxisSize:
MainAxisSize
.
min
,
...
...
@@ -736,17 +765,12 @@ class _DatePickerHeader extends StatelessWidget {
@override
Widget
build
(
BuildContext
context
)
{
final
ThemeData
theme
=
Theme
.
of
(
context
);
final
ColorScheme
colorScheme
=
theme
.
colorScheme
;
final
TextTheme
textTheme
=
theme
.
textTheme
;
// The header should use the primary color in light themes and surface color in dark
final
bool
isDark
=
colorScheme
.
brightness
==
Brightness
.
dark
;
final
Color
primarySurfaceColor
=
isDark
?
colorScheme
.
surface
:
colorScheme
.
primary
;
final
Color
onPrimarySurfaceColor
=
isDark
?
colorScheme
.
onSurface
:
colorScheme
.
onPrimary
;
final
TextStyle
?
helpStyle
=
textTheme
.
labelSmall
?.
copyWith
(
color:
onPrimarySurfaceColor
,
final
DatePickerThemeData
themeData
=
DatePickerTheme
.
of
(
context
);
final
DatePickerThemeData
defaults
=
DatePickerTheme
.
defaults
(
context
);
final
Color
?
backgroundColor
=
themeData
.
headerBackgroundColor
??
defaults
.
headerBackgroundColor
;
final
Color
?
foregroundColor
=
themeData
.
headerForegroundColor
??
defaults
.
headerForegroundColor
;
final
TextStyle
?
helpStyle
=
(
themeData
.
headerHelpStyle
??
defaults
.
headerHelpStyle
)?.
copyWith
(
color:
foregroundColor
,
);
final
Text
help
=
Text
(
...
...
@@ -768,7 +792,7 @@ class _DatePickerHeader extends StatelessWidget {
return
SizedBox
(
height:
_datePickerHeaderPortraitHeight
,
child:
Material
(
color:
primarySurface
Color
,
color:
background
Color
,
child:
Padding
(
padding:
const
EdgeInsetsDirectional
.
only
(
start:
24
,
...
...
@@ -796,7 +820,7 @@ class _DatePickerHeader extends StatelessWidget {
return
SizedBox
(
width:
_datePickerHeaderLandscapeWidth
,
child:
Material
(
color:
primarySurface
Color
,
color:
background
Color
,
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
<
Widget
>[
...
...
@@ -1292,18 +1316,20 @@ class _DateRangePickerDialogState extends State<DateRangePickerDialog> with Rest
@override
Widget
build
(
BuildContext
context
)
{
final
ThemeData
theme
=
Theme
.
of
(
context
);
final
bool
useMaterial3
=
theme
.
useMaterial3
;
final
Orientation
orientation
=
MediaQuery
.
orientationOf
(
context
);
final
double
textScaleFactor
=
math
.
min
(
MediaQuery
.
textScaleFactorOf
(
context
),
1.3
);
final
MaterialLocalizations
localizations
=
MaterialLocalizations
.
of
(
context
);
final
ColorScheme
colors
=
Theme
.
of
(
context
).
colorScheme
;
final
Color
onPrimarySurface
=
colors
.
brightness
==
Brightness
.
light
?
colors
.
onPrimary
:
colors
.
onSurface
;
final
DatePickerThemeData
datePickerTheme
=
DatePickerTheme
.
of
(
context
);
final
DatePickerThemeData
defaults
=
DatePickerTheme
.
defaults
(
context
);
final
Widget
contents
;
final
Size
size
;
ShapeBorder
?
shape
;
final
double
elevation
;
final
double
?
elevation
;
final
Color
?
shadowColor
;
final
Color
?
surfaceTintColor
;
final
ShapeBorder
?
shape
;
final
EdgeInsets
insetPadding
;
final
bool
showEntryModeButton
=
_entryMode
.
value
==
DatePickerEntryMode
.
calendar
||
...
...
@@ -1324,28 +1350,29 @@ class _DateRangePickerDialogState extends State<DateRangePickerDialog> with Rest
onCancel:
_handleCancel
,
entryModeButton:
showEntryModeButton
?
IconButton
(
icon:
const
Icon
(
Icons
.
edit
),
icon:
Icon
(
useMaterial3
?
Icons
.
edit_outlined
:
Icons
.
edit
),
padding:
EdgeInsets
.
zero
,
color:
onPrimarySurface
,
tooltip:
localizations
.
inputDateModeButtonLabel
,
onPressed:
_handleEntryModeToggle
,
)
:
null
,
confirmText:
widget
.
saveText
??
(
Theme
.
of
(
context
).
useMaterial3
useMaterial3
?
localizations
.
saveButtonLabel
:
localizations
.
saveButtonLabel
.
toUpperCase
()
),
helpText:
widget
.
helpText
??
(
Theme
.
of
(
context
).
useMaterial3
useMaterial3
?
localizations
.
dateRangePickerHelpText
:
localizations
.
dateRangePickerHelpText
.
toUpperCase
()
),
);
size
=
MediaQuery
.
sizeOf
(
context
);
insetPadding
=
EdgeInsets
.
zero
;
shape
=
const
RoundedRectangleBorder
();
elevation
=
0
;
elevation
=
datePickerTheme
.
rangePickerElevation
??
defaults
.
rangePickerElevation
!;
shadowColor
=
datePickerTheme
.
rangePickerShadowColor
??
defaults
.
rangePickerShadowColor
!;
surfaceTintColor
=
datePickerTheme
.
rangePickerSurfaceTintColor
??
defaults
.
rangePickerSurfaceTintColor
!;
shape
=
datePickerTheme
.
rangePickerShape
??
defaults
.
rangePickerShape
;
break
;
case
DatePickerEntryMode
.
input
:
...
...
@@ -1391,35 +1418,46 @@ class _DateRangePickerDialogState extends State<DateRangePickerDialog> with Rest
?
IconButton
(
icon:
const
Icon
(
Icons
.
calendar_today
),
padding:
EdgeInsets
.
zero
,
color:
onPrimarySurface
,
tooltip:
localizations
.
calendarModeButtonLabel
,
onPressed:
_handleEntryModeToggle
,
)
:
null
,
confirmText:
widget
.
confirmText
??
localizations
.
okButtonLabel
,
cancelText:
widget
.
cancelText
??
(
Theme
.
of
(
context
).
useMaterial3
useMaterial3
?
localizations
.
cancelButtonLabel
:
localizations
.
cancelButtonLabel
.
toUpperCase
()
),
helpText:
widget
.
helpText
??
(
Theme
.
of
(
context
).
useMaterial3
useMaterial3
?
localizations
.
dateRangePickerHelpText
:
localizations
.
dateRangePickerHelpText
.
toUpperCase
()
),
);
final
DialogTheme
dialogTheme
=
Theme
.
of
(
context
).
dialogTheme
;
size
=
orientation
==
Orientation
.
portrait
?
_inputPortraitDialogSize
:
_inputRangeLandscapeDialogSize
;
final
DialogTheme
dialogTheme
=
theme
.
dialogTheme
;
size
=
orientation
==
Orientation
.
portrait
?
(
useMaterial3
?
_inputPortraitDialogSizeM3
:
_inputPortraitDialogSizeM2
)
:
_inputRangeLandscapeDialogSize
;
elevation
=
useMaterial3
?
datePickerTheme
.
elevation
??
defaults
.
elevation
!
:
datePickerTheme
.
elevation
??
dialogTheme
.
elevation
??
24
;
shadowColor
=
datePickerTheme
.
shadowColor
??
defaults
.
shadowColor
;
surfaceTintColor
=
datePickerTheme
.
surfaceTintColor
??
defaults
.
surfaceTintColor
;
shape
=
useMaterial3
?
datePickerTheme
.
shape
??
defaults
.
shape
:
datePickerTheme
.
shape
??
dialogTheme
.
shape
??
defaults
.
shape
;
insetPadding
=
const
EdgeInsets
.
symmetric
(
horizontal:
16.0
,
vertical:
24.0
);
shape
=
dialogTheme
.
shape
;
elevation
=
dialogTheme
.
elevation
??
24
;
break
;
}
return
Dialog
(
insetPadding:
insetPadding
,
shape:
shape
,
backgroundColor:
datePickerTheme
.
backgroundColor
??
defaults
.
backgroundColor
,
elevation:
elevation
,
shadowColor:
shadowColor
,
surfaceTintColor:
surfaceTintColor
,
shape:
shape
,
clipBehavior:
Clip
.
antiAlias
,
child:
AnimatedContainer
(
width:
size
.
width
,
...
...
@@ -1472,26 +1510,29 @@ class _CalendarRangePickerDialog extends StatelessWidget {
@override
Widget
build
(
BuildContext
context
)
{
final
ThemeData
theme
=
Theme
.
of
(
context
);
final
ColorScheme
colorScheme
=
theme
.
colorScheme
;
final
bool
useMaterial3
=
theme
.
useMaterial3
;
final
MaterialLocalizations
localizations
=
MaterialLocalizations
.
of
(
context
);
final
Orientation
orientation
=
MediaQuery
.
orientationOf
(
context
);
final
TextTheme
textTheme
=
theme
.
textTheme
;
final
Color
headerForeground
=
colorScheme
.
brightness
==
Brightness
.
light
?
colorScheme
.
onPrimary
:
colorScheme
.
onSurface
;
final
Color
headerDisabledForeground
=
headerForeground
.
withOpacity
(
0.38
);
final
DatePickerThemeData
themeData
=
DatePickerTheme
.
of
(
context
);
final
DatePickerThemeData
defaults
=
DatePickerTheme
.
defaults
(
context
);
final
Color
?
dialogBackground
=
themeData
.
rangePickerBackgroundColor
??
defaults
.
rangePickerBackgroundColor
;
final
Color
?
headerForeground
=
themeData
.
rangePickerHeaderForegroundColor
??
defaults
.
rangePickerHeaderForegroundColor
;
final
Color
?
headerDisabledForeground
=
headerForeground
?.
withOpacity
(
0.38
);
final
TextStyle
?
headlineStyle
=
themeData
.
rangePickerHeaderHeadlineStyle
??
defaults
.
rangePickerHeaderHeadlineStyle
;
final
TextStyle
?
headlineHelpStyle
=
(
themeData
.
rangePickerHeaderHelpStyle
??
defaults
.
rangePickerHeaderHelpStyle
)?.
apply
(
color:
headerForeground
);
final
String
startDateText
=
_formatRangeStartDate
(
localizations
,
selectedStartDate
,
selectedEndDate
);
final
String
endDateText
=
_formatRangeEndDate
(
localizations
,
selectedStartDate
,
selectedEndDate
,
DateTime
.
now
());
final
TextStyle
?
headlineStyle
=
textTheme
.
headlineSmall
;
final
TextStyle
?
startDateStyle
=
headlineStyle
?.
apply
(
color:
selectedStartDate
!=
null
?
headerForeground
:
headerDisabledForeground
,
);
final
TextStyle
?
endDateStyle
=
headlineStyle
?.
apply
(
color:
selectedEndDate
!=
null
?
headerForeground
:
headerDisabledForeground
,
);
final
TextStyle
saveButtonStyle
=
textTheme
.
labelLarge
!.
apply
(
color:
onConfirm
!=
null
?
headerForeground
:
headerDisabledForeground
,
final
ButtonStyle
buttonStyle
=
TextButton
.
styleFrom
(
foregroundColor:
headerForeground
,
disabledForegroundColor:
headerDisabledForeground
);
final
IconThemeData
iconTheme
=
IconThemeData
(
color:
headerForeground
);
return
SafeArea
(
top:
false
,
...
...
@@ -1499,6 +1540,11 @@ class _CalendarRangePickerDialog extends StatelessWidget {
right:
false
,
child:
Scaffold
(
appBar:
AppBar
(
iconTheme:
iconTheme
,
actionsIconTheme:
iconTheme
,
elevation:
useMaterial3
?
0
:
null
,
scrolledUnderElevation:
useMaterial3
?
0
:
null
,
backgroundColor:
useMaterial3
?
Colors
.
transparent
:
null
,
leading:
CloseButton
(
onPressed:
onCancel
,
),
...
...
@@ -1506,8 +1552,9 @@ class _CalendarRangePickerDialog extends StatelessWidget {
if
(
orientation
==
Orientation
.
landscape
&&
entryModeButton
!=
null
)
entryModeButton
!,
TextButton
(
style:
buttonStyle
,
onPressed:
onConfirm
,
child:
Text
(
confirmText
,
style:
saveButtonStyle
),
child:
Text
(
confirmText
),
),
const
SizedBox
(
width:
8
),
],
...
...
@@ -1522,12 +1569,7 @@ class _CalendarRangePickerDialog extends StatelessWidget {
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
<
Widget
>[
Text
(
helpText
,
style:
textTheme
.
labelSmall
!.
apply
(
color:
headerForeground
,
),
),
Text
(
helpText
,
style:
headlineHelpStyle
),
const
SizedBox
(
height:
8
),
Row
(
children:
<
Widget
>[
...
...
@@ -1557,11 +1599,15 @@ class _CalendarRangePickerDialog extends StatelessWidget {
if
(
orientation
==
Orientation
.
portrait
&&
entryModeButton
!=
null
)
Padding
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
8.0
),
child:
entryModeButton
,
child:
IconTheme
(
data:
iconTheme
,
child:
entryModeButton
!,
),
),
]),
),
),
backgroundColor:
dialogBackground
,
body:
_CalendarDateRangePicker
(
initialStartDate:
selectedStartDate
,
initialEndDate:
selectedEndDate
,
...
...
@@ -2201,7 +2247,8 @@ class _MonthItemState extends State<_MonthItem> {
}
Color
_highlightColor
(
BuildContext
context
)
{
return
Theme
.
of
(
context
).
colorScheme
.
primary
.
withOpacity
(
0.12
);
return
DatePickerTheme
.
of
(
context
).
rangeSelectionBackgroundColor
??
DatePickerTheme
.
defaults
(
context
).
rangeSelectionBackgroundColor
!;
}
void
_dayFocusChanged
(
bool
focused
)
{
...
...
@@ -2232,6 +2279,8 @@ class _MonthItemState extends State<_MonthItem> {
final
ColorScheme
colorScheme
=
theme
.
colorScheme
;
final
TextTheme
textTheme
=
theme
.
textTheme
;
final
MaterialLocalizations
localizations
=
MaterialLocalizations
.
of
(
context
);
final
DatePickerThemeData
datePickerTheme
=
DatePickerTheme
.
of
(
context
);
final
DatePickerThemeData
defaults
=
DatePickerTheme
.
defaults
(
context
);
final
TextDirection
textDirection
=
Directionality
.
of
(
context
);
final
Color
highlightColor
=
_highlightColor
(
context
);
final
int
day
=
dayToBuild
.
day
;
...
...
@@ -2248,14 +2297,42 @@ class _MonthItemState extends State<_MonthItem> {
dayToBuild
.
isAfter
(
widget
.
selectedDateStart
!)
&&
dayToBuild
.
isBefore
(
widget
.
selectedDateEnd
!);
T
?
effectiveValue
<
T
>(
T
?
Function
(
DatePickerThemeData
?
theme
)
getProperty
)
{
return
getProperty
(
datePickerTheme
)
??
getProperty
(
defaults
);
}
T
?
resolve
<
T
>(
MaterialStateProperty
<
T
>?
Function
(
DatePickerThemeData
?
theme
)
getProperty
,
Set
<
MaterialState
>
states
)
{
return
effectiveValue
(
(
DatePickerThemeData
?
theme
)
{
return
getProperty
(
theme
)?.
resolve
(
states
);
},
);
}
final
Set
<
MaterialState
>
states
=
<
MaterialState
>{
if
(
isDisabled
)
MaterialState
.
disabled
,
if
(
isSelectedDayStart
||
isSelectedDayEnd
)
MaterialState
.
selected
,
};
final
Color
?
dayForegroundColor
=
resolve
<
Color
?>((
DatePickerThemeData
?
theme
)
=>
theme
?.
dayForegroundColor
,
states
);
final
Color
?
dayBackgroundColor
=
resolve
<
Color
?>((
DatePickerThemeData
?
theme
)
=>
theme
?.
dayBackgroundColor
,
states
);
final
MaterialStateProperty
<
Color
?>
dayOverlayColor
=
MaterialStateProperty
.
resolveWith
<
Color
?>(
(
Set
<
MaterialState
>
states
)
=>
effectiveValue
(
(
DatePickerThemeData
?
theme
)
=>
isInRange
?
theme
?.
rangeSelectionOverlayColor
?.
resolve
(
states
)
:
theme
?.
dayOverlayColor
?.
resolve
(
states
),
)
);
_HighlightPainter
?
highlightPainter
;
if
(
isSelectedDayStart
||
isSelectedDayEnd
)
{
// The selected start and end dates gets a circle background
// highlight, and a contrasting text color.
itemStyle
=
textTheme
.
bodyMedium
?.
apply
(
color:
colorScheme
.
onPrimary
);
itemStyle
=
textTheme
.
bodyMedium
?.
apply
(
color:
dayForegroundColor
);
decoration
=
BoxDecoration
(
color:
colorScheme
.
primary
,
color:
dayBackgroundColor
,
shape:
BoxShape
.
circle
,
);
...
...
@@ -2327,7 +2404,8 @@ class _MonthItemState extends State<_MonthItem> {
focusNode:
_dayFocusNodes
[
day
-
1
],
onTap:
()
=>
widget
.
onChanged
(
dayToBuild
),
radius:
_monthItemRowHeight
/
2
+
4
,
splashColor:
colorScheme
.
primary
.
withOpacity
(
0.38
),
statesController:
MaterialStatesController
(
states
),
overlayColor:
dayOverlayColor
,
onFocusChange:
_dayFocusChanged
,
child:
dayWidget
,
);
...
...
@@ -2350,8 +2428,7 @@ class _MonthItemState extends State<_MonthItem> {
final
int
daysInMonth
=
DateUtils
.
getDaysInMonth
(
year
,
month
);
final
int
dayOffset
=
DateUtils
.
firstDayOffset
(
year
,
month
,
localizations
);
final
int
weeks
=
((
daysInMonth
+
dayOffset
)
/
DateTime
.
daysPerWeek
).
ceil
();
final
double
gridHeight
=
weeks
*
_monthItemRowHeight
+
(
weeks
-
1
)
*
_monthItemSpaceBetweenRows
;
final
double
gridHeight
=
weeks
*
_monthItemRowHeight
+
(
weeks
-
1
)
*
_monthItemSpaceBetweenRows
;
final
List
<
Widget
>
dayItems
=
<
Widget
>[];
for
(
int
i
=
0
;
true
;
i
+=
1
)
{
...
...
@@ -2566,18 +2643,17 @@ class _InputDateRangePickerDialog extends StatelessWidget {
@override
Widget
build
(
BuildContext
context
)
{
final
ThemeData
theme
=
Theme
.
of
(
context
);
final
ColorScheme
colorScheme
=
theme
.
colorScheme
;
final
bool
useMaterial3
=
Theme
.
of
(
context
).
useMaterial3
;
final
MaterialLocalizations
localizations
=
MaterialLocalizations
.
of
(
context
);
final
Orientation
orientation
=
MediaQuery
.
orientationOf
(
context
);
final
TextTheme
textTheme
=
theme
.
textTheme
;
final
DatePickerThemeData
datePickerTheme
=
DatePickerTheme
.
of
(
context
);
final
DatePickerThemeData
defaults
=
DatePickerTheme
.
defaults
(
context
);
final
Color
?
headerForegroundColor
=
datePickerTheme
.
headerForegroundColor
??
defaults
.
headerForegroundColor
;
final
TextStyle
?
headlineStyle
=
(
datePickerTheme
.
headerHeadlineStyle
??
defaults
.
headerHeadlineStyle
)?.
copyWith
(
color:
headerForegroundColor
,
);
final
Color
onPrimarySurfaceColor
=
colorScheme
.
brightness
==
Brightness
.
light
?
colorScheme
.
onPrimary
:
colorScheme
.
onSurface
;
final
TextStyle
?
dateStyle
=
orientation
==
Orientation
.
landscape
?
textTheme
.
headlineSmall
?.
apply
(
color:
onPrimarySurfaceColor
)
:
textTheme
.
headlineMedium
?.
apply
(
color:
onPrimarySurfaceColor
);
final
String
dateText
=
_formatDateRange
(
context
,
selectedStartDate
,
selectedEndDate
,
currentDate
!);
final
String
semanticDateText
=
selectedStartDate
!=
null
&&
selectedEndDate
!=
null
?
'
${localizations.formatMediumDate(selectedStartDate!)}
–
${localizations.formatMediumDate(selectedEndDate!)}
'
...
...
@@ -2585,13 +2661,13 @@ class _InputDateRangePickerDialog extends StatelessWidget {
final
Widget
header
=
_DatePickerHeader
(
helpText:
helpText
??
(
Theme
.
of
(
context
).
useMaterial3
useMaterial3
?
localizations
.
dateRangePickerHelpText
:
localizations
.
dateRangePickerHelpText
.
toUpperCase
()
),
titleText:
dateText
,
titleSemanticsLabel:
semanticDateText
,
titleStyle:
dat
eStyle
,
titleStyle:
headlin
eStyle
,
orientation:
orientation
,
isShort:
orientation
==
Orientation
.
landscape
,
entryModeButton:
entryModeButton
,
...
...
@@ -2607,7 +2683,7 @@ class _InputDateRangePickerDialog extends StatelessWidget {
TextButton
(
onPressed:
onCancel
,
child:
Text
(
cancelText
??
(
theme
.
useMaterial3
useMaterial3
?
localizations
.
cancelButtonLabel
:
localizations
.
cancelButtonLabel
.
toUpperCase
()
)),
...
...
@@ -2856,8 +2932,13 @@ class _InputDateRangePickerState extends State<_InputDateRangePicker> {
@override
Widget
build
(
BuildContext
context
)
{
final
ThemeData
theme
=
Theme
.
of
(
context
);
final
bool
useMaterial3
=
theme
.
useMaterial3
;
final
MaterialLocalizations
localizations
=
MaterialLocalizations
.
of
(
context
);
final
InputDecorationTheme
inputTheme
=
Theme
.
of
(
context
).
inputDecorationTheme
;
final
InputDecorationTheme
inputTheme
=
theme
.
inputDecorationTheme
;
final
InputBorder
inputBorder
=
inputTheme
.
border
??
(
useMaterial3
?
const
OutlineInputBorder
()
:
const
UnderlineInputBorder
());
return
Row
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
<
Widget
>[
...
...
@@ -2865,7 +2946,7 @@ class _InputDateRangePickerState extends State<_InputDateRangePicker> {
child:
TextField
(
controller:
_startController
,
decoration:
InputDecoration
(
border:
input
Theme
.
border
??
const
UnderlineInputBorder
()
,
border:
input
Border
,
filled:
inputTheme
.
filled
,
hintText:
widget
.
fieldStartHintText
??
localizations
.
dateHelpText
,
labelText:
widget
.
fieldStartLabelText
??
localizations
.
dateRangeStartLabel
,
...
...
@@ -2881,7 +2962,7 @@ class _InputDateRangePickerState extends State<_InputDateRangePicker> {
child:
TextField
(
controller:
_endController
,
decoration:
InputDecoration
(
border:
input
Theme
.
border
??
const
UnderlineInputBorder
()
,
border:
input
Border
,
filled:
inputTheme
.
filled
,
hintText:
widget
.
fieldEndHintText
??
localizations
.
dateHelpText
,
labelText:
widget
.
fieldEndLabelText
??
localizations
.
dateRangeEndLabel
,
...
...
packages/flutter/lib/src/material/date_picker_theme.dart
0 → 100644
View file @
198a51ac
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'dart:ui'
show
lerpDouble
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/widgets.dart'
;
import
'color_scheme.dart'
;
import
'colors.dart'
;
import
'material_state.dart'
;
import
'text_theme.dart'
;
import
'theme.dart'
;
// Examples can assume:
// late BuildContext context;
/// Overrides the default values of visual properties for descendant
/// [DatePickerDialog] widgets.
///
/// Descendant widgets obtain the current [DatePickerThemeData] object with
/// [DatePickerTheme.of]. Instances of [DatePickerTheme] can
/// be customized with [DatePickerThemeData.copyWith].
///
/// Typically a [DatePickerTheme] is specified as part of the overall
/// [Theme] with [ThemeData.datePickerTheme].
///
/// All [DatePickerThemeData] properties are null by default. When null,
/// the [DatePickerDialog] computes its own default values, typically based on
/// the overall theme's [ThemeData.colorScheme], [ThemeData.textTheme], and
/// [ThemeData.iconTheme].
@immutable
class
DatePickerThemeData
with
Diagnosticable
{
/// Creates a [DatePickerThemeData] that can be used to override default properties
/// in a [DatePickerTheme] widget.
const
DatePickerThemeData
({
this
.
backgroundColor
,
this
.
elevation
,
this
.
shadowColor
,
this
.
surfaceTintColor
,
this
.
shape
,
this
.
headerBackgroundColor
,
this
.
headerForegroundColor
,
this
.
headerHeadlineStyle
,
this
.
headerHelpStyle
,
this
.
weekdayStyle
,
this
.
dayStyle
,
this
.
dayForegroundColor
,
this
.
dayBackgroundColor
,
this
.
dayOverlayColor
,
this
.
todayForegroundColor
,
this
.
todayBackgroundColor
,
this
.
todayBorder
,
this
.
yearStyle
,
this
.
yearForegroundColor
,
this
.
yearBackgroundColor
,
this
.
yearOverlayColor
,
this
.
rangePickerBackgroundColor
,
this
.
rangePickerElevation
,
this
.
rangePickerShadowColor
,
this
.
rangePickerSurfaceTintColor
,
this
.
rangePickerShape
,
this
.
rangePickerHeaderBackgroundColor
,
this
.
rangePickerHeaderForegroundColor
,
this
.
rangePickerHeaderHeadlineStyle
,
this
.
rangePickerHeaderHelpStyle
,
this
.
rangeSelectionBackgroundColor
,
this
.
rangeSelectionOverlayColor
,
});
/// Overrides the default value of [Dialog.backgroundColor].
final
Color
?
backgroundColor
;
/// Overrides the default value of [Dialog.elevation].
///
/// See also:
/// [Material.elevation], which explains how elevation is related to a component's shadow.
final
double
?
elevation
;
/// Overrides the default value of [Dialog.shadowColor].
///
/// See also:
/// [Material.shadowColor], which explains how the shadow is rendered.
final
Color
?
shadowColor
;
/// Overrides the default value of [Dialog.surfaceTintColor].
///
/// See also:
/// [Material.surfaceTintColor], which explains how this color is related to
/// [elevation] and [backgroundColor].
final
Color
?
surfaceTintColor
;
/// Overrides the default value of [Dialog.shape].
///
/// If [elevation] is greater than zero then a shadow is shown and the shadow's
/// shape mirrors the shape of the dialog.
final
ShapeBorder
?
shape
;
/// Overrides the header's default background fill color.
///
/// The dialog's header displays the currently selected date.
final
Color
?
headerBackgroundColor
;
/// Overrides the header's default color used for text labels and icons.
///
/// The dialog's header displays the currently selected date.
///
/// This is used instead of the [TextStyle.color] property of [headerHeadlineStyle]
/// and [headerHelpStyle].
final
Color
?
headerForegroundColor
;
/// Overrides the header's default headline text style.
///
/// The dialog's header displays the currently selected date.
///
/// The [TextStyle.color] of the [headerHeadlineStyle] is not used,
/// [headerForegroundColor] is used instead.
final
TextStyle
?
headerHeadlineStyle
;
/// Overrides the header's default help text style.
///
/// The help text (also referred to as "supporting text" in the Material
/// spec) is usually a prompt to the user at the top of the header
/// (i.e. 'Select date').
///
/// The [TextStyle.color] of the [headerHelpStyle] is not used,
/// [headerForegroundColor] is used instead.
///
/// See also:
/// [DatePickerDialog.helpText], which specifies the help text.
final
TextStyle
?
headerHelpStyle
;
/// Overrides the default text style used for the row of weekday
/// labels at the top of the date picker grid.
final
TextStyle
?
weekdayStyle
;
/// Overrides the default text style used for each individual day
/// label in the grid of the date picker.
///
/// The [TextStyle.color] of the [dayStyle] is not used,
/// [dayForegroundColor] is used instead.
final
TextStyle
?
dayStyle
;
/// Overrides the default color used to paint the day labels in the
/// grid of the date picker.
///
/// This will be used instead of the color provided in [dayStyle].
final
MaterialStateProperty
<
Color
?>?
dayForegroundColor
;
/// Overrides the default color used to paint the background of the
/// day labels in the grid of the date picker.
final
MaterialStateProperty
<
Color
?>?
dayBackgroundColor
;
/// Overriddes the default highlight color that's typically used to
/// indicate that a day in the grid is focused, hovered, or pressed.
final
MaterialStateProperty
<
Color
?>?
dayOverlayColor
;
/// Overrides the default color used to paint the
/// [DatePickerDialog.currentDate] label in the grid of the dialog's
/// [CalendarDatePicker] and the corresponding year in the dialog's
/// [YearPicker].
///
/// This will be used instead of the [TextStyle.color] provided in [dayStyle].
final
MaterialStateProperty
<
Color
?>?
todayForegroundColor
;
/// Overrides the default color used to paint the background of the
/// [DatePickerDialog.currentDate] label in the grid of the date picker.
final
MaterialStateProperty
<
Color
?>?
todayBackgroundColor
;
/// Overrides the border used to paint the
/// [DatePickerDialog.currentDate] label in the grid of the date
/// picker.
///
/// The border side's [BorderSide.color] is not used,
/// [todayForegroundColor] is used instead.
final
BorderSide
?
todayBorder
;
/// Overrides the default text style used to paint each of the year
/// entries in the year selector of the date picker.
///
/// The [TextStyle.color] of the [yearStyle] is not used,
/// [yearForegroundColor] is used instead.
final
TextStyle
?
yearStyle
;
/// Overrides the default color used to paint the year labels in the year
/// selector of the date picker.
///
/// This will be used instead of the color provided in [yearStyle].
final
MaterialStateProperty
<
Color
?>?
yearForegroundColor
;
/// Overrides the default color used to paint the background of the
/// year labels in the year selector of the of the date picker.
final
MaterialStateProperty
<
Color
?>?
yearBackgroundColor
;
/// Overrides the default highlight color that's typically used to
/// indicate that a year in the year selector is focused, hovered,
/// or pressed.
final
MaterialStateProperty
<
Color
?>?
yearOverlayColor
;
/// Overrides the default [Scaffold.backgroundColor] for
/// [DateRangePickerDialog].
final
Color
?
rangePickerBackgroundColor
;
/// Overrides the default elevation of the full screen
/// [DateRangePickerDialog].
///
/// See also:
/// [Material.elevation], which explains how elevation is related to a component's shadow.
final
double
?
rangePickerElevation
;
/// Overrides the color of the shadow painted below a full screen
/// [DateRangePickerDialog].
///
/// See also:
/// [Material.shadowColor], which explains how the shadow is rendered.
final
Color
?
rangePickerShadowColor
;
/// Overrides the default color of the surface tint overlay applied
/// to the [backgroundColor] of a full screen
/// [DateRangePickerDialog]'s to indicate elevation.
///
/// See also:
/// [Material.surfaceTintColor], which explains how this color is related to
/// [elevation].
final
Color
?
rangePickerSurfaceTintColor
;
/// Overrides the default overall shape of a full screen
/// [DateRangePickerDialog].
///
/// If [elevation] is greater than zero then a shadow is shown and the shadow's
/// shape mirrors the shape of the dialog.
///
/// [Material.surfaceTintColor], which explains how this color is related to
/// [elevation].
final
ShapeBorder
?
rangePickerShape
;
/// Overrides the default background fill color for [DateRangePickerDialog].
///
/// The dialog's header displays the currently selected date range.
final
Color
?
rangePickerHeaderBackgroundColor
;
/// Overrides the default color used for text labels and icons in
/// the header of a full screen [DateRangePickerDialog]
///
/// The dialog's header displays the currently selected date range.
///
/// This is used instead of any colors provided by
/// [rangePickerHeaderHeadlineStyle] or [rangePickerHeaderHelpStyle].
final
Color
?
rangePickerHeaderForegroundColor
;
/// Overrides the default text style used for the headline text in
/// the header of a full screen [DateRangePickerDialog].
///
/// The dialog's header displays the currently selected date range.
///
/// The [TextStyle.color] of [rangePickerHeaderHeadlineStyle] is not used,
/// [rangePickerHeaderForegroundColor] is used instead.
final
TextStyle
?
rangePickerHeaderHeadlineStyle
;
/// Overrides the default text style used for the help text of the
/// header of a full screen [DateRangePickerDialog].
///
/// The help text (also referred to as "supporting text" in the Material
/// spec) is usually a prompt to the user at the top of the header
/// (i.e. 'Select date').
///
/// The [TextStyle.color] of the [rangePickerHeaderHelpStyle] is not used,
/// [rangePickerHeaderForegroundColor] is used instead.
///
/// See also:
/// [DateRangePickerDialog.helpText], which specifies the help text.
final
TextStyle
?
rangePickerHeaderHelpStyle
;
/// Overrides the default background color used to paint days
/// selected between the start and end dates in a
/// [DateRangePickerDialog].
final
Color
?
rangeSelectionBackgroundColor
;
/// Overrides the default highlight color that's typically used to
/// indicate that a date in the selected range of a
/// [DateRangePickerDialog] is focused, hovered, or pressed.
final
MaterialStateProperty
<
Color
?>?
rangeSelectionOverlayColor
;
/// Creates a copy of this object with the given fields replaced with the
/// new values.
DatePickerThemeData
copyWith
({
Color
?
backgroundColor
,
double
?
elevation
,
Color
?
shadowColor
,
Color
?
surfaceTintColor
,
ShapeBorder
?
shape
,
Color
?
headerBackgroundColor
,
Color
?
headerForegroundColor
,
TextStyle
?
headerHeadlineStyle
,
TextStyle
?
headerHelpStyle
,
TextStyle
?
weekdayStyle
,
TextStyle
?
dayStyle
,
MaterialStateProperty
<
Color
?>?
dayForegroundColor
,
MaterialStateProperty
<
Color
?>?
dayBackgroundColor
,
MaterialStateProperty
<
Color
?>?
dayOverlayColor
,
MaterialStateProperty
<
Color
?>?
todayForegroundColor
,
MaterialStateProperty
<
Color
?>?
todayBackgroundColor
,
BorderSide
?
todayBorder
,
TextStyle
?
yearStyle
,
MaterialStateProperty
<
Color
?>?
yearForegroundColor
,
MaterialStateProperty
<
Color
?>?
yearBackgroundColor
,
MaterialStateProperty
<
Color
?>?
yearOverlayColor
,
Color
?
rangePickerBackgroundColor
,
double
?
rangePickerElevation
,
Color
?
rangePickerShadowColor
,
Color
?
rangePickerSurfaceTintColor
,
ShapeBorder
?
rangePickerShape
,
Color
?
rangePickerHeaderBackgroundColor
,
Color
?
rangePickerHeaderForegroundColor
,
TextStyle
?
rangePickerHeaderHeadlineStyle
,
TextStyle
?
rangePickerHeaderHelpStyle
,
Color
?
rangeSelectionBackgroundColor
,
MaterialStateProperty
<
Color
?>?
rangeSelectionOverlayColor
,
})
{
return
DatePickerThemeData
(
backgroundColor:
backgroundColor
??
this
.
backgroundColor
,
elevation:
elevation
??
this
.
elevation
,
shadowColor:
shadowColor
??
this
.
shadowColor
,
surfaceTintColor:
surfaceTintColor
??
this
.
surfaceTintColor
,
shape:
shape
??
this
.
shape
,
headerBackgroundColor:
headerBackgroundColor
??
this
.
headerBackgroundColor
,
headerForegroundColor:
headerForegroundColor
??
this
.
headerForegroundColor
,
headerHeadlineStyle:
headerHeadlineStyle
??
this
.
headerHeadlineStyle
,
headerHelpStyle:
headerHelpStyle
??
this
.
headerHelpStyle
,
weekdayStyle:
weekdayStyle
??
this
.
weekdayStyle
,
dayStyle:
dayStyle
??
this
.
dayStyle
,
dayForegroundColor:
dayForegroundColor
??
this
.
dayForegroundColor
,
dayBackgroundColor:
dayBackgroundColor
??
this
.
dayBackgroundColor
,
dayOverlayColor:
dayOverlayColor
??
this
.
dayOverlayColor
,
todayForegroundColor:
todayForegroundColor
??
this
.
todayForegroundColor
,
todayBackgroundColor:
todayBackgroundColor
??
this
.
todayBackgroundColor
,
todayBorder:
todayBorder
??
this
.
todayBorder
,
yearStyle:
yearStyle
??
this
.
yearStyle
,
yearForegroundColor:
yearForegroundColor
??
this
.
yearForegroundColor
,
yearBackgroundColor:
yearBackgroundColor
??
this
.
yearBackgroundColor
,
yearOverlayColor:
yearOverlayColor
??
this
.
yearOverlayColor
,
rangePickerBackgroundColor:
rangePickerBackgroundColor
??
this
.
rangePickerBackgroundColor
,
rangePickerElevation:
rangePickerElevation
??
this
.
rangePickerElevation
,
rangePickerShadowColor:
rangePickerShadowColor
??
this
.
rangePickerShadowColor
,
rangePickerSurfaceTintColor:
rangePickerSurfaceTintColor
??
this
.
rangePickerSurfaceTintColor
,
rangePickerShape:
rangePickerShape
??
this
.
rangePickerShape
,
rangePickerHeaderBackgroundColor:
rangePickerHeaderBackgroundColor
??
this
.
rangePickerHeaderBackgroundColor
,
rangePickerHeaderForegroundColor:
rangePickerHeaderForegroundColor
??
this
.
rangePickerHeaderForegroundColor
,
rangePickerHeaderHeadlineStyle:
rangePickerHeaderHeadlineStyle
??
this
.
rangePickerHeaderHeadlineStyle
,
rangePickerHeaderHelpStyle:
rangePickerHeaderHelpStyle
??
this
.
rangePickerHeaderHelpStyle
,
rangeSelectionBackgroundColor:
rangeSelectionBackgroundColor
??
this
.
rangeSelectionBackgroundColor
,
rangeSelectionOverlayColor:
rangeSelectionOverlayColor
??
this
.
rangeSelectionOverlayColor
,
);
}
/// Linearly interpolates between two [DatePickerThemeData].
static
DatePickerThemeData
lerp
(
DatePickerThemeData
?
a
,
DatePickerThemeData
?
b
,
double
t
)
{
return
DatePickerThemeData
(
backgroundColor:
Color
.
lerp
(
a
?.
backgroundColor
,
b
?.
backgroundColor
,
t
),
elevation:
lerpDouble
(
a
?.
elevation
,
b
?.
elevation
,
t
),
shadowColor:
Color
.
lerp
(
a
?.
shadowColor
,
b
?.
shadowColor
,
t
),
surfaceTintColor:
Color
.
lerp
(
a
?.
surfaceTintColor
,
b
?.
surfaceTintColor
,
t
),
shape:
ShapeBorder
.
lerp
(
a
?.
shape
,
b
?.
shape
,
t
),
headerBackgroundColor:
Color
.
lerp
(
a
?.
headerBackgroundColor
,
b
?.
headerBackgroundColor
,
t
),
headerForegroundColor:
Color
.
lerp
(
a
?.
headerForegroundColor
,
b
?.
headerForegroundColor
,
t
),
headerHeadlineStyle:
TextStyle
.
lerp
(
a
?.
headerHeadlineStyle
,
b
?.
headerHeadlineStyle
,
t
),
headerHelpStyle:
TextStyle
.
lerp
(
a
?.
headerHelpStyle
,
b
?.
headerHelpStyle
,
t
),
weekdayStyle:
TextStyle
.
lerp
(
a
?.
weekdayStyle
,
b
?.
weekdayStyle
,
t
),
dayStyle:
TextStyle
.
lerp
(
a
?.
dayStyle
,
b
?.
dayStyle
,
t
),
dayForegroundColor:
MaterialStateProperty
.
lerp
<
Color
?>(
a
?.
dayForegroundColor
,
b
?.
dayForegroundColor
,
t
,
Color
.
lerp
),
dayBackgroundColor:
MaterialStateProperty
.
lerp
<
Color
?>(
a
?.
dayBackgroundColor
,
b
?.
dayBackgroundColor
,
t
,
Color
.
lerp
),
dayOverlayColor:
MaterialStateProperty
.
lerp
<
Color
?>(
a
?.
dayOverlayColor
,
b
?.
dayOverlayColor
,
t
,
Color
.
lerp
),
todayForegroundColor:
MaterialStateProperty
.
lerp
<
Color
?>(
a
?.
todayForegroundColor
,
b
?.
todayForegroundColor
,
t
,
Color
.
lerp
),
todayBackgroundColor:
MaterialStateProperty
.
lerp
<
Color
?>(
a
?.
todayBackgroundColor
,
b
?.
todayBackgroundColor
,
t
,
Color
.
lerp
),
todayBorder:
_lerpBorderSide
(
a
?.
todayBorder
,
b
?.
todayBorder
,
t
),
yearStyle:
TextStyle
.
lerp
(
a
?.
yearStyle
,
b
?.
yearStyle
,
t
),
yearForegroundColor:
MaterialStateProperty
.
lerp
<
Color
?>(
a
?.
yearForegroundColor
,
b
?.
yearForegroundColor
,
t
,
Color
.
lerp
),
yearBackgroundColor:
MaterialStateProperty
.
lerp
<
Color
?>(
a
?.
yearBackgroundColor
,
b
?.
yearBackgroundColor
,
t
,
Color
.
lerp
),
yearOverlayColor:
MaterialStateProperty
.
lerp
<
Color
?>(
a
?.
yearOverlayColor
,
b
?.
yearOverlayColor
,
t
,
Color
.
lerp
),
rangePickerBackgroundColor:
Color
.
lerp
(
a
?.
rangePickerBackgroundColor
,
b
?.
rangePickerBackgroundColor
,
t
),
rangePickerElevation:
lerpDouble
(
a
?.
rangePickerElevation
,
b
?.
rangePickerElevation
,
t
),
rangePickerShadowColor:
Color
.
lerp
(
a
?.
rangePickerShadowColor
,
b
?.
rangePickerShadowColor
,
t
),
rangePickerSurfaceTintColor:
Color
.
lerp
(
a
?.
rangePickerSurfaceTintColor
,
b
?.
rangePickerSurfaceTintColor
,
t
),
rangePickerShape:
ShapeBorder
.
lerp
(
a
?.
rangePickerShape
,
b
?.
rangePickerShape
,
t
),
rangePickerHeaderBackgroundColor:
Color
.
lerp
(
a
?.
rangePickerHeaderBackgroundColor
,
b
?.
rangePickerHeaderBackgroundColor
,
t
),
rangePickerHeaderForegroundColor:
Color
.
lerp
(
a
?.
rangePickerHeaderForegroundColor
,
b
?.
rangePickerHeaderForegroundColor
,
t
),
rangePickerHeaderHeadlineStyle:
TextStyle
.
lerp
(
a
?.
rangePickerHeaderHeadlineStyle
,
b
?.
rangePickerHeaderHeadlineStyle
,
t
),
rangePickerHeaderHelpStyle:
TextStyle
.
lerp
(
a
?.
rangePickerHeaderHelpStyle
,
b
?.
rangePickerHeaderHelpStyle
,
t
),
rangeSelectionBackgroundColor:
Color
.
lerp
(
a
?.
rangeSelectionBackgroundColor
,
b
?.
rangeSelectionBackgroundColor
,
t
),
rangeSelectionOverlayColor:
MaterialStateProperty
.
lerp
<
Color
?>(
a
?.
rangeSelectionOverlayColor
,
b
?.
rangeSelectionOverlayColor
,
t
,
Color
.
lerp
),
);
}
static
BorderSide
?
_lerpBorderSide
(
BorderSide
?
a
,
BorderSide
?
b
,
double
t
)
{
if
(
a
==
null
&&
b
==
null
)
{
return
null
;
}
if
(
a
==
null
)
{
return
BorderSide
.
lerp
(
BorderSide
(
width:
0
,
color:
b
!.
color
.
withAlpha
(
0
)),
b
,
t
);
}
return
BorderSide
.
lerp
(
a
,
BorderSide
(
width:
0
,
color:
a
.
color
.
withAlpha
(
0
)),
t
);
}
@override
int
get
hashCode
=>
Object
.
hashAll
(<
Object
?>[
backgroundColor
,
elevation
,
shadowColor
,
surfaceTintColor
,
shape
,
headerBackgroundColor
,
headerForegroundColor
,
headerHeadlineStyle
,
headerHelpStyle
,
weekdayStyle
,
dayStyle
,
dayForegroundColor
,
dayBackgroundColor
,
dayOverlayColor
,
todayForegroundColor
,
todayBackgroundColor
,
todayBorder
,
yearStyle
,
yearForegroundColor
,
yearBackgroundColor
,
yearOverlayColor
,
rangePickerBackgroundColor
,
rangePickerElevation
,
rangePickerShadowColor
,
rangePickerSurfaceTintColor
,
rangePickerShape
,
rangePickerHeaderBackgroundColor
,
rangePickerHeaderForegroundColor
,
rangePickerHeaderHeadlineStyle
,
rangePickerHeaderHelpStyle
,
rangeSelectionBackgroundColor
,
rangeSelectionOverlayColor
,
]);
@override
bool
operator
==(
Object
other
)
{
if
(
identical
(
this
,
other
))
{
return
true
;
}
return
other
is
DatePickerThemeData
&&
other
.
backgroundColor
==
backgroundColor
&&
other
.
elevation
==
elevation
&&
other
.
shadowColor
==
shadowColor
&&
other
.
surfaceTintColor
==
surfaceTintColor
&&
other
.
shape
==
shape
&&
other
.
headerBackgroundColor
==
headerBackgroundColor
&&
other
.
headerForegroundColor
==
headerForegroundColor
&&
other
.
headerHeadlineStyle
==
headerHeadlineStyle
&&
other
.
headerHelpStyle
==
headerHelpStyle
&&
other
.
weekdayStyle
==
weekdayStyle
&&
other
.
dayStyle
==
dayStyle
&&
other
.
dayForegroundColor
==
dayForegroundColor
&&
other
.
dayBackgroundColor
==
dayBackgroundColor
&&
other
.
dayOverlayColor
==
dayOverlayColor
&&
other
.
todayForegroundColor
==
todayForegroundColor
&&
other
.
todayBackgroundColor
==
todayBackgroundColor
&&
other
.
todayBorder
==
todayBorder
&&
other
.
yearStyle
==
yearStyle
&&
other
.
yearForegroundColor
==
yearForegroundColor
&&
other
.
yearBackgroundColor
==
yearBackgroundColor
&&
other
.
yearOverlayColor
==
yearOverlayColor
&&
other
.
rangePickerBackgroundColor
==
rangePickerBackgroundColor
&&
other
.
rangePickerElevation
==
rangePickerElevation
&&
other
.
rangePickerShadowColor
==
rangePickerShadowColor
&&
other
.
rangePickerSurfaceTintColor
==
rangePickerSurfaceTintColor
&&
other
.
rangePickerShape
==
rangePickerShape
&&
other
.
rangePickerHeaderBackgroundColor
==
rangePickerHeaderBackgroundColor
&&
other
.
rangePickerHeaderForegroundColor
==
rangePickerHeaderForegroundColor
&&
other
.
rangePickerHeaderHeadlineStyle
==
rangePickerHeaderHeadlineStyle
&&
other
.
rangePickerHeaderHelpStyle
==
rangePickerHeaderHelpStyle
&&
other
.
rangeSelectionBackgroundColor
==
rangeSelectionBackgroundColor
&&
other
.
rangeSelectionOverlayColor
==
rangeSelectionOverlayColor
;
}
@override
void
debugFillProperties
(
DiagnosticPropertiesBuilder
properties
)
{
super
.
debugFillProperties
(
properties
);
properties
.
add
(
ColorProperty
(
'backgroundColor'
,
backgroundColor
,
defaultValue:
null
));
properties
.
add
(
DoubleProperty
(
'elevation'
,
elevation
,
defaultValue:
null
));
properties
.
add
(
ColorProperty
(
'shadowColor'
,
shadowColor
,
defaultValue:
null
));
properties
.
add
(
ColorProperty
(
'surfaceTintColor'
,
surfaceTintColor
,
defaultValue:
null
));
properties
.
add
(
DiagnosticsProperty
<
ShapeBorder
>(
'shape'
,
shape
,
defaultValue:
null
));
properties
.
add
(
ColorProperty
(
'headerBackgroundColor'
,
headerBackgroundColor
,
defaultValue:
null
));
properties
.
add
(
ColorProperty
(
'headerForegroundColor'
,
headerForegroundColor
,
defaultValue:
null
));
properties
.
add
(
DiagnosticsProperty
<
TextStyle
>(
'headerHeadlineStyle'
,
headerHeadlineStyle
,
defaultValue:
null
));
properties
.
add
(
DiagnosticsProperty
<
TextStyle
>(
'headerHelpStyle'
,
headerHelpStyle
,
defaultValue:
null
));
properties
.
add
(
DiagnosticsProperty
<
TextStyle
>(
'weekDayStyle'
,
weekdayStyle
,
defaultValue:
null
));
properties
.
add
(
DiagnosticsProperty
<
TextStyle
>(
'dayStyle'
,
dayStyle
,
defaultValue:
null
));
properties
.
add
(
DiagnosticsProperty
<
MaterialStateProperty
<
Color
?>>(
'dayForegroundColor'
,
dayForegroundColor
,
defaultValue:
null
));
properties
.
add
(
DiagnosticsProperty
<
MaterialStateProperty
<
Color
?>>(
'dayBackgroundColor'
,
dayBackgroundColor
,
defaultValue:
null
));
properties
.
add
(
DiagnosticsProperty
<
MaterialStateProperty
<
Color
?>>(
'dayOverlayColor'
,
dayOverlayColor
,
defaultValue:
null
));
properties
.
add
(
DiagnosticsProperty
<
MaterialStateProperty
<
Color
?>>(
'todayForegroundColor'
,
todayForegroundColor
,
defaultValue:
null
));
properties
.
add
(
DiagnosticsProperty
<
MaterialStateProperty
<
Color
?>>(
'todayBackgroundColor'
,
todayBackgroundColor
,
defaultValue:
null
));
properties
.
add
(
DiagnosticsProperty
<
BorderSide
?>(
'todayBorder'
,
todayBorder
,
defaultValue:
null
));
properties
.
add
(
DiagnosticsProperty
<
TextStyle
>(
'yearStyle'
,
yearStyle
,
defaultValue:
null
));
properties
.
add
(
DiagnosticsProperty
<
MaterialStateProperty
<
Color
?>>(
'yearForegroundColor'
,
yearForegroundColor
,
defaultValue:
null
));
properties
.
add
(
DiagnosticsProperty
<
MaterialStateProperty
<
Color
?>>(
'yearBackgroundColor'
,
yearBackgroundColor
,
defaultValue:
null
));
properties
.
add
(
DiagnosticsProperty
<
MaterialStateProperty
<
Color
?>>(
'yearOverlayColor'
,
yearOverlayColor
,
defaultValue:
null
));
properties
.
add
(
ColorProperty
(
'rangePickerBackgroundColor'
,
rangePickerBackgroundColor
,
defaultValue:
null
));
properties
.
add
(
DoubleProperty
(
'rangePickerElevation'
,
rangePickerElevation
,
defaultValue:
null
));
properties
.
add
(
ColorProperty
(
'rangePickerShadowColor'
,
rangePickerShadowColor
,
defaultValue:
null
));
properties
.
add
(
ColorProperty
(
'rangePickerSurfaceTintColor'
,
rangePickerSurfaceTintColor
,
defaultValue:
null
));
properties
.
add
(
DiagnosticsProperty
<
ShapeBorder
>(
'rangePickerShape'
,
rangePickerShape
,
defaultValue:
null
));
properties
.
add
(
ColorProperty
(
'rangePickerHeaderBackgroundColor'
,
rangePickerHeaderBackgroundColor
,
defaultValue:
null
));
properties
.
add
(
ColorProperty
(
'rangePickerHeaderForegroundColor'
,
rangePickerHeaderForegroundColor
,
defaultValue:
null
));
properties
.
add
(
DiagnosticsProperty
<
TextStyle
>(
'rangePickerHeaderHeadlineStyle'
,
rangePickerHeaderHeadlineStyle
,
defaultValue:
null
));
properties
.
add
(
DiagnosticsProperty
<
TextStyle
>(
'rangePickerHeaderHelpStyle'
,
rangePickerHeaderHelpStyle
,
defaultValue:
null
));
properties
.
add
(
ColorProperty
(
'rangeSelectionBackgroundColor'
,
rangeSelectionBackgroundColor
,
defaultValue:
null
));
properties
.
add
(
DiagnosticsProperty
<
MaterialStateProperty
<
Color
?>>(
'rangeSelectionOverlayColor'
,
rangeSelectionOverlayColor
,
defaultValue:
null
));
}
}
/// An inherited widget that defines the visual properties for
/// [DatePickerDialog]s in this widget's subtree.
///
/// Values specified here are used for [DatePickerDialog] properties that are not
/// given an explicit non-null value.
class
DatePickerTheme
extends
InheritedTheme
{
/// Creates a [DatePickerTheme] that controls visual parameters for
/// descendent [DatePickerDialog]s.
const
DatePickerTheme
({
super
.
key
,
required
this
.
data
,
required
super
.
child
,
});
/// Specifies the visual properties used by descendant [DatePickerDialog]
/// widgets.
final
DatePickerThemeData
data
;
/// The [data] from the closest instance of this class that encloses the given
/// context.
///
/// If there is no [DatePickerTheme] in scope, this will return
/// [ThemeData.datePickerTheme] from the ambient [Theme].
///
/// Typical usage is as follows:
///
/// ```dart
/// DatePickerThemeData theme = DatePickerTheme.of(context);
/// ```
///
/// See also:
///
/// * [maybeOf], which returns null if it doesn't find a
/// [DatePickerTheme] ancestor.
/// * [defaults], which will return the default properties used when no
/// other [DatePickerTheme] has been provided.
static
DatePickerThemeData
of
(
BuildContext
context
)
{
return
maybeOf
(
context
)
??
Theme
.
of
(
context
).
datePickerTheme
;
}
/// The data from the closest instance of this class that encloses the given
/// context, if any.
///
/// Use this function if you want to allow situations where no
/// [DatePickerTheme] is in scope. Prefer using [DatePickerTheme.of]
/// in situations where a [DatePickerThemeData] is expected to be
/// non-null.
///
/// If there is no [DatePickerTheme] in scope, then this function will
/// return null.
///
/// Typical usage is as follows:
///
/// ```dart
/// DatePickerThemeData? theme = DatePickerTheme.maybeOf(context);
/// if (theme == null) {
/// // Do something else instead.
/// }
/// ```
///
/// See also:
///
/// * [of], which will return [ThemeData.datePickerTheme] if it doesn't
/// find a [DatePickerTheme] ancestor, instead of returning null.
/// * [defaults], which will return the default properties used when no
/// other [DatePickerTheme] has been provided.
static
DatePickerThemeData
?
maybeOf
(
BuildContext
context
)
{
return
context
.
dependOnInheritedWidgetOfExactType
<
DatePickerTheme
>()?.
data
;
}
/// A DatePickerThemeData used as the default properties for date pickers.
///
/// This is only used for properties not already specified in the ambient
/// [DatePickerTheme.of].
///
/// See also:
///
/// * [of], which will return [ThemeData.datePickerTheme] if it doesn't
/// find a [DatePickerTheme] ancestor, instead of returning null.
/// * [maybeOf], which returns null if it doesn't find a
/// [DatePickerTheme] ancestor.
static
DatePickerThemeData
defaults
(
BuildContext
context
)
{
return
Theme
.
of
(
context
).
useMaterial3
?
_DatePickerDefaultsM3
(
context
)
:
_DatePickerDefaultsM2
(
context
);
}
@override
Widget
wrap
(
BuildContext
context
,
Widget
child
)
{
return
DatePickerTheme
(
data:
data
,
child:
child
);
}
@override
bool
updateShouldNotify
(
DatePickerTheme
oldWidget
)
=>
data
!=
oldWidget
.
data
;
}
// Hand coded defaults based on Material Design 2.
class
_DatePickerDefaultsM2
extends
DatePickerThemeData
{
_DatePickerDefaultsM2
(
this
.
context
)
:
super
(
elevation:
24.0
,
shape:
const
RoundedRectangleBorder
(
borderRadius:
BorderRadius
.
all
(
Radius
.
circular
(
4.0
))),
rangePickerElevation:
0.0
,
rangePickerShape:
const
RoundedRectangleBorder
(),
);
final
BuildContext
context
;
late
final
ThemeData
_theme
=
Theme
.
of
(
context
);
late
final
ColorScheme
_colors
=
_theme
.
colorScheme
;
late
final
TextTheme
_textTheme
=
_theme
.
textTheme
;
late
final
bool
_isDark
=
_colors
.
brightness
==
Brightness
.
dark
;
@override
Color
?
get
headerBackgroundColor
=>
_isDark
?
_colors
.
surface
:
_colors
.
primary
;
@override
Color
?
get
headerForegroundColor
=>
_isDark
?
_colors
.
onSurface
:
_colors
.
onPrimary
;
@override
TextStyle
?
get
headerHeadlineStyle
=>
_textTheme
.
headlineSmall
;
@override
TextStyle
?
get
headerHelpStyle
=>
_textTheme
.
labelSmall
;
@override
TextStyle
?
get
weekdayStyle
=>
_textTheme
.
bodySmall
?.
apply
(
color:
_colors
.
onSurface
.
withOpacity
(
0.60
),
);
@override
TextStyle
?
get
dayStyle
=>
_textTheme
.
bodySmall
;
@override
MaterialStateProperty
<
Color
?>?
get
dayForegroundColor
=>
MaterialStateProperty
.
resolveWith
((
Set
<
MaterialState
>
states
)
{
if
(
states
.
contains
(
MaterialState
.
selected
))
{
return
_colors
.
onPrimary
;
}
else
if
(
states
.
contains
(
MaterialState
.
disabled
))
{
return
_colors
.
onSurface
.
withOpacity
(
0.38
);
}
return
_colors
.
onSurface
;
});
@override
MaterialStateProperty
<
Color
?>?
get
dayBackgroundColor
=>
MaterialStateProperty
.
resolveWith
((
Set
<
MaterialState
>
states
)
{
if
(
states
.
contains
(
MaterialState
.
selected
))
{
return
_colors
.
primary
;
}
return
null
;
});
@override
MaterialStateProperty
<
Color
?>?
get
dayOverlayColor
=>
MaterialStateProperty
.
resolveWith
((
Set
<
MaterialState
>
states
)
{
if
(
states
.
contains
(
MaterialState
.
selected
))
{
if
(
states
.
contains
(
MaterialState
.
hovered
))
{
return
_colors
.
onPrimary
.
withOpacity
(
0.08
);
}
if
(
states
.
contains
(
MaterialState
.
focused
))
{
return
_colors
.
onPrimary
.
withOpacity
(
0.12
);
}
if
(
states
.
contains
(
MaterialState
.
pressed
))
{
return
_colors
.
onPrimary
.
withOpacity
(
0.38
);
}
}
else
{
if
(
states
.
contains
(
MaterialState
.
hovered
))
{
return
_colors
.
onSurfaceVariant
.
withOpacity
(
0.08
);
}
if
(
states
.
contains
(
MaterialState
.
focused
))
{
return
_colors
.
onSurfaceVariant
.
withOpacity
(
0.12
);
}
if
(
states
.
contains
(
MaterialState
.
pressed
))
{
return
_colors
.
onSurfaceVariant
.
withOpacity
(
0.12
);
}
}
return
null
;
});
@override
MaterialStateProperty
<
Color
?>?
get
todayForegroundColor
=>
MaterialStateProperty
.
resolveWith
((
Set
<
MaterialState
>
states
)
{
if
(
states
.
contains
(
MaterialState
.
selected
))
{
return
_colors
.
onPrimary
;
}
else
if
(
states
.
contains
(
MaterialState
.
disabled
))
{
return
_colors
.
onSurface
.
withOpacity
(
0.38
);
}
return
_colors
.
primary
;
});
@override
MaterialStateProperty
<
Color
?>?
get
todayBackgroundColor
=>
dayBackgroundColor
;
@override
BorderSide
?
get
todayBorder
=>
BorderSide
(
color:
_colors
.
primary
);
@override
TextStyle
?
get
yearStyle
=>
_textTheme
.
bodyLarge
;
@override
Color
?
get
rangePickerBackgroundColor
=>
_colors
.
surface
;
@override
Color
?
get
rangePickerShadowColor
=>
Colors
.
transparent
;
@override
Color
?
get
rangePickerSurfaceTintColor
=>
Colors
.
transparent
;
@override
Color
?
get
rangePickerHeaderBackgroundColor
=>
_isDark
?
_colors
.
surface
:
_colors
.
primary
;
@override
Color
?
get
rangePickerHeaderForegroundColor
=>
_isDark
?
_colors
.
onSurface
:
_colors
.
onPrimary
;
@override
TextStyle
?
get
rangePickerHeaderHeadlineStyle
=>
_textTheme
.
headlineSmall
;
@override
TextStyle
?
get
rangePickerHeaderHelpStyle
=>
_textTheme
.
labelSmall
;
@override
Color
?
get
rangeSelectionBackgroundColor
=>
_colors
.
primary
.
withOpacity
(
0.12
);
@override
MaterialStateProperty
<
Color
?>?
get
rangeSelectionOverlayColor
=>
MaterialStateProperty
.
resolveWith
((
Set
<
MaterialState
>
states
)
{
if
(
states
.
contains
(
MaterialState
.
selected
))
{
if
(
states
.
contains
(
MaterialState
.
hovered
))
{
return
_colors
.
onPrimary
.
withOpacity
(
0.08
);
}
if
(
states
.
contains
(
MaterialState
.
focused
))
{
return
_colors
.
onPrimary
.
withOpacity
(
0.12
);
}
if
(
states
.
contains
(
MaterialState
.
pressed
))
{
return
_colors
.
onPrimary
.
withOpacity
(
0.38
);
}
}
else
{
if
(
states
.
contains
(
MaterialState
.
hovered
))
{
return
_colors
.
onSurfaceVariant
.
withOpacity
(
0.08
);
}
if
(
states
.
contains
(
MaterialState
.
focused
))
{
return
_colors
.
onSurfaceVariant
.
withOpacity
(
0.12
);
}
if
(
states
.
contains
(
MaterialState
.
pressed
))
{
return
_colors
.
onSurfaceVariant
.
withOpacity
(
0.12
);
}
}
return
null
;
});
}
// BEGIN GENERATED TOKEN PROPERTIES - DatePicker
// Do not edit by hand. The code between the "BEGIN GENERATED" and
// "END GENERATED" comments are generated from data in the Material
// Design token database by the script:
// dev/tools/gen_defaults/bin/gen_defaults.dart.
// Token database version: v0_150
class
_DatePickerDefaultsM3
extends
DatePickerThemeData
{
_DatePickerDefaultsM3
(
this
.
context
)
:
super
(
elevation:
6.0
,
shape:
const
RoundedRectangleBorder
(
borderRadius:
BorderRadius
.
all
(
Radius
.
circular
(
28.0
))),
rangePickerElevation:
0.0
,
rangePickerShape:
const
RoundedRectangleBorder
(),
);
final
BuildContext
context
;
late
final
ThemeData
_theme
=
Theme
.
of
(
context
);
late
final
ColorScheme
_colors
=
_theme
.
colorScheme
;
late
final
TextTheme
_textTheme
=
_theme
.
textTheme
;
@override
Color
?
get
backgroundColor
=>
_colors
.
surface
;
@override
Color
?
get
shadowColor
=>
Colors
.
transparent
;
@override
Color
?
get
surfaceTintColor
=>
_colors
.
surfaceTint
;
@override
Color
?
get
headerBackgroundColor
=>
Colors
.
transparent
;
@override
Color
?
get
headerForegroundColor
=>
_colors
.
onSurfaceVariant
;
@override
TextStyle
?
get
headerHeadlineStyle
=>
_textTheme
.
headlineLarge
;
@override
TextStyle
?
get
headerHelpStyle
=>
_textTheme
.
labelMedium
;
@override
TextStyle
?
get
weekdayStyle
=>
_textTheme
.
bodySmall
?.
apply
(
color:
_colors
.
onSurface
,
);
@override
TextStyle
?
get
dayStyle
=>
_textTheme
.
bodySmall
;
@override
MaterialStateProperty
<
Color
?>?
get
dayForegroundColor
=>
MaterialStateProperty
.
resolveWith
((
Set
<
MaterialState
>
states
)
{
if
(
states
.
contains
(
MaterialState
.
selected
))
{
return
_colors
.
onPrimary
;
}
else
if
(
states
.
contains
(
MaterialState
.
disabled
))
{
return
_colors
.
onSurface
.
withOpacity
(
0.38
);
}
return
_colors
.
onSurface
;
});
@override
MaterialStateProperty
<
Color
?>?
get
dayBackgroundColor
=>
MaterialStateProperty
.
resolveWith
((
Set
<
MaterialState
>
states
)
{
if
(
states
.
contains
(
MaterialState
.
selected
))
{
return
_colors
.
primary
;
}
return
null
;
});
@override
MaterialStateProperty
<
Color
?>?
get
dayOverlayColor
=>
MaterialStateProperty
.
resolveWith
((
Set
<
MaterialState
>
states
)
{
if
(
states
.
contains
(
MaterialState
.
selected
))
{
if
(
states
.
contains
(
MaterialState
.
hovered
))
{
return
_colors
.
onPrimary
.
withOpacity
(
0.08
);
}
if
(
states
.
contains
(
MaterialState
.
focused
))
{
return
_colors
.
onPrimary
.
withOpacity
(
0.12
);
}
if
(
states
.
contains
(
MaterialState
.
pressed
))
{
return
_colors
.
onPrimary
.
withOpacity
(
0.12
);
}
}
else
{
if
(
states
.
contains
(
MaterialState
.
hovered
))
{
return
_colors
.
onSurfaceVariant
.
withOpacity
(
0.08
);
}
if
(
states
.
contains
(
MaterialState
.
focused
))
{
return
_colors
.
onSurfaceVariant
.
withOpacity
(
0.12
);
}
if
(
states
.
contains
(
MaterialState
.
pressed
))
{
return
_colors
.
onSurfaceVariant
.
withOpacity
(
0.12
);
}
}
return
null
;
});
@override
MaterialStateProperty
<
Color
?>?
get
todayForegroundColor
=>
MaterialStateProperty
.
resolveWith
((
Set
<
MaterialState
>
states
)
{
if
(
states
.
contains
(
MaterialState
.
selected
))
{
return
_colors
.
onPrimary
;
}
else
if
(
states
.
contains
(
MaterialState
.
disabled
))
{
return
_colors
.
primary
.
withOpacity
(
0.38
);
}
return
_colors
.
primary
;
});
@override
MaterialStateProperty
<
Color
?>?
get
todayBackgroundColor
=>
dayBackgroundColor
;
@override
BorderSide
?
get
todayBorder
=>
BorderSide
(
color:
_colors
.
primary
);
@override
TextStyle
?
get
yearStyle
=>
_textTheme
.
bodyLarge
;
@override
MaterialStateProperty
<
Color
?>?
get
yearForegroundColor
=>
MaterialStateProperty
.
resolveWith
((
Set
<
MaterialState
>
states
)
{
if
(
states
.
contains
(
MaterialState
.
selected
))
{
return
_colors
.
onPrimary
;
}
else
if
(
states
.
contains
(
MaterialState
.
disabled
))
{
return
_colors
.
onSurfaceVariant
.
withOpacity
(
0.38
);
}
return
_colors
.
onSurfaceVariant
;
});
@override
MaterialStateProperty
<
Color
?>?
get
yearBackgroundColor
=>
MaterialStateProperty
.
resolveWith
((
Set
<
MaterialState
>
states
)
{
if
(
states
.
contains
(
MaterialState
.
selected
))
{
return
_colors
.
primary
;
}
return
null
;
});
@override
MaterialStateProperty
<
Color
?>?
get
yearOverlayColor
=>
MaterialStateProperty
.
resolveWith
((
Set
<
MaterialState
>
states
)
{
if
(
states
.
contains
(
MaterialState
.
selected
))
{
if
(
states
.
contains
(
MaterialState
.
hovered
))
{
return
_colors
.
onPrimary
.
withOpacity
(
0.08
);
}
if
(
states
.
contains
(
MaterialState
.
focused
))
{
return
_colors
.
onPrimary
.
withOpacity
(
0.12
);
}
if
(
states
.
contains
(
MaterialState
.
pressed
))
{
return
_colors
.
onPrimary
.
withOpacity
(
0.12
);
}
}
else
{
if
(
states
.
contains
(
MaterialState
.
hovered
))
{
return
_colors
.
onSurfaceVariant
.
withOpacity
(
0.08
);
}
if
(
states
.
contains
(
MaterialState
.
focused
))
{
return
_colors
.
onSurfaceVariant
.
withOpacity
(
0.12
);
}
if
(
states
.
contains
(
MaterialState
.
pressed
))
{
return
_colors
.
onSurfaceVariant
.
withOpacity
(
0.12
);
}
}
return
null
;
});
@override
Color
?
get
rangePickerShadowColor
=>
Colors
.
transparent
;
@override
Color
?
get
rangePickerSurfaceTintColor
=>
Colors
.
transparent
;
@override
Color
?
get
rangeSelectionBackgroundColor
=>
_colors
.
primaryContainer
;
@override
MaterialStateProperty
<
Color
?>?
get
rangeSelectionOverlayColor
=>
MaterialStateProperty
.
resolveWith
((
Set
<
MaterialState
>
states
)
{
if
(
states
.
contains
(
MaterialState
.
hovered
))
{
return
null
;
}
if
(
states
.
contains
(
MaterialState
.
focused
))
{
return
null
;
}
if
(
states
.
contains
(
MaterialState
.
pressed
))
{
return
null
;
}
return
null
;
});
@override
Color
?
get
rangePickerHeaderBackgroundColor
=>
Colors
.
transparent
;
@override
Color
?
get
rangePickerHeaderForegroundColor
=>
_colors
.
onSurfaceVariant
;
@override
TextStyle
?
get
rangePickerHeaderHeadlineStyle
=>
_textTheme
.
titleLarge
;
@override
TextStyle
?
get
rangePickerHeaderHelpStyle
=>
_textTheme
.
titleSmall
;
}
// END GENERATED TOKEN PROPERTIES - DatePicker
packages/flutter/lib/src/material/input_date_picker_form_field.dart
View file @
198a51ac
...
...
@@ -234,11 +234,16 @@ class _InputDatePickerFormFieldState extends State<InputDatePickerFormField> {
@override
Widget
build
(
BuildContext
context
)
{
final
ThemeData
theme
=
Theme
.
of
(
context
);
final
bool
useMaterial3
=
theme
.
useMaterial3
;
final
MaterialLocalizations
localizations
=
MaterialLocalizations
.
of
(
context
);
final
InputDecorationTheme
inputTheme
=
Theme
.
of
(
context
).
inputDecorationTheme
;
final
InputDecorationTheme
inputTheme
=
theme
.
inputDecorationTheme
;
final
InputBorder
inputBorder
=
inputTheme
.
border
??
(
useMaterial3
?
const
OutlineInputBorder
()
:
const
UnderlineInputBorder
());
return
TextFormField
(
decoration:
InputDecoration
(
border:
input
Theme
.
border
??
const
UnderlineInputBorder
()
,
border:
input
Border
,
filled:
inputTheme
.
filled
,
hintText:
widget
.
fieldHintText
??
localizations
.
dateHelpText
,
labelText:
widget
.
fieldLabelText
??
localizations
.
dateInputLabel
,
...
...
packages/flutter/lib/src/material/material.dart
View file @
198a51ac
...
...
@@ -254,6 +254,7 @@ class Material extends StatefulWidget {
/// The color to paint the shadow below the material.
///
/// {@template flutter.material.material.shadowColor}
/// If null and [ThemeData.useMaterial3] is true then [ThemeData]'s
/// [ColorScheme.shadow] will be used. If [ThemeData.useMaterial3] is false
/// then [ThemeData.shadowColor] will be used.
...
...
@@ -266,11 +267,13 @@ class Material extends StatefulWidget {
/// property if it is null.
/// * [ThemeData.applyElevationOverlayColor], which turns elevation overlay
/// on or off for dark themes.
/// {@endtemplate}
final
Color
?
shadowColor
;
/// The color of the surface tint overlay applied to the material color
/// to indicate elevation.
///
/// {@template flutter.material.material.surfaceTintColor}
/// Material Design 3 introduced a new way for some components to indicate
/// their elevation by using a surface tint color overlay on top of the
/// base material [color]. This overlay is painted with an opacity that is
...
...
@@ -291,6 +294,7 @@ class Material extends StatefulWidget {
/// tint.
/// * https://m3.material.io/styles/color/the-color-system/color-roles
/// which specifies how the overlay is applied.
/// {@endtemplate}
final
Color
?
surfaceTintColor
;
/// The typographical style to use for text within this material.
...
...
@@ -298,11 +302,13 @@ class Material extends StatefulWidget {
/// Defines the material's shape as well its shadow.
///
/// {@template flutter.material.material.shape}
/// If shape is non null, the [borderRadius] is ignored and the material's
/// clip boundary and shadow are defined by the shape.
///
/// A shadow is only displayed if the [elevation] is greater than
/// zero.
/// {@endtemplate}
final
ShapeBorder
?
shape
;
/// Whether to paint the [shape] border in front of the [child].
...
...
packages/flutter/lib/src/material/theme_data.dart
View file @
198a51ac
...
...
@@ -22,6 +22,7 @@ import 'color_scheme.dart';
import
'colors.dart'
;
import
'constants.dart'
;
import
'data_table_theme.dart'
;
import
'date_picker_theme.dart'
;
import
'dialog_theme.dart'
;
import
'divider_theme.dart'
;
import
'drawer_theme.dart'
;
...
...
@@ -348,6 +349,7 @@ class ThemeData with Diagnosticable {
CheckboxThemeData
?
checkboxTheme
,
ChipThemeData
?
chipTheme
,
DataTableThemeData
?
dataTableTheme
,
DatePickerThemeData
?
datePickerTheme
,
DialogTheme
?
dialogTheme
,
DividerThemeData
?
dividerTheme
,
DrawerThemeData
?
drawerTheme
,
...
...
@@ -600,6 +602,7 @@ class ThemeData with Diagnosticable {
checkboxTheme
??=
const
CheckboxThemeData
();
chipTheme
??=
const
ChipThemeData
();
dataTableTheme
??=
const
DataTableThemeData
();
datePickerTheme
??=
const
DatePickerThemeData
();
dialogTheme
??=
const
DialogTheme
();
dividerTheme
??=
const
DividerThemeData
();
drawerTheme
??=
const
DrawerThemeData
();
...
...
@@ -697,6 +700,7 @@ class ThemeData with Diagnosticable {
checkboxTheme:
checkboxTheme
,
chipTheme:
chipTheme
,
dataTableTheme:
dataTableTheme
,
datePickerTheme:
datePickerTheme
,
dialogTheme:
dialogTheme
,
dividerTheme:
dividerTheme
,
drawerTheme:
drawerTheme
,
...
...
@@ -810,6 +814,7 @@ class ThemeData with Diagnosticable {
required
this
.
checkboxTheme
,
required
this
.
chipTheme
,
required
this
.
dataTableTheme
,
required
this
.
datePickerTheme
,
required
this
.
dialogTheme
,
required
this
.
dividerTheme
,
required
this
.
drawerTheme
,
...
...
@@ -1238,6 +1243,7 @@ class ThemeData with Diagnosticable {
/// - [ActionChip] (used for Assist and Suggestion chips),
/// - [FilterChip], [ChoiceChip] (used for single selection filter chips),
/// - [InputChip]
/// * Date pickers: [showDatePicker], [showDateRangePicker], [DatePickerDialog], [DateRangePickerDialog], [InputDatePickerFormField]
/// * Dialogs: [Dialog], [AlertDialog]
/// * Divider: [Divider]
/// * Lists: [ListTile]
...
...
@@ -1252,6 +1258,7 @@ class ThemeData with Diagnosticable {
/// * Switch: [Switch]
/// * Tabs: [TabBar]
/// * TextFields: [TextField] together with its [InputDecoration]
/// * Time pickers: [showTimePicker], [TimePickerDialog]
/// * Top app bar: [AppBar]
///
/// In addition, this flag enables features introduced in Android 12.
...
...
@@ -1473,6 +1480,10 @@ class ThemeData with Diagnosticable {
/// widgets.
final
DataTableThemeData
dataTableTheme
;
/// A theme for customizing the appearance and layout of [DatePickerDialog]
/// widgets.
final
DatePickerThemeData
datePickerTheme
;
/// A theme for customizing the shape of a dialog.
final
DialogTheme
dialogTheme
;
...
...
@@ -1811,6 +1822,7 @@ class ThemeData with Diagnosticable {
CheckboxThemeData
?
checkboxTheme
,
ChipThemeData
?
chipTheme
,
DataTableThemeData
?
dataTableTheme
,
DatePickerThemeData
?
datePickerTheme
,
DialogTheme
?
dialogTheme
,
DividerThemeData
?
dividerTheme
,
DrawerThemeData
?
drawerTheme
,
...
...
@@ -1971,6 +1983,7 @@ class ThemeData with Diagnosticable {
checkboxTheme:
checkboxTheme
??
this
.
checkboxTheme
,
chipTheme:
chipTheme
??
this
.
chipTheme
,
dataTableTheme:
dataTableTheme
??
this
.
dataTableTheme
,
datePickerTheme:
datePickerTheme
??
this
.
datePickerTheme
,
dialogTheme:
dialogTheme
??
this
.
dialogTheme
,
dividerTheme:
dividerTheme
??
this
.
dividerTheme
,
drawerTheme:
drawerTheme
??
this
.
drawerTheme
,
...
...
@@ -2165,6 +2178,7 @@ class ThemeData with Diagnosticable {
checkboxTheme:
CheckboxThemeData
.
lerp
(
a
.
checkboxTheme
,
b
.
checkboxTheme
,
t
),
chipTheme:
ChipThemeData
.
lerp
(
a
.
chipTheme
,
b
.
chipTheme
,
t
)!,
dataTableTheme:
DataTableThemeData
.
lerp
(
a
.
dataTableTheme
,
b
.
dataTableTheme
,
t
),
datePickerTheme:
DatePickerThemeData
.
lerp
(
a
.
datePickerTheme
,
b
.
datePickerTheme
,
t
),
dialogTheme:
DialogTheme
.
lerp
(
a
.
dialogTheme
,
b
.
dialogTheme
,
t
),
dividerTheme:
DividerThemeData
.
lerp
(
a
.
dividerTheme
,
b
.
dividerTheme
,
t
),
drawerTheme:
DrawerThemeData
.
lerp
(
a
.
drawerTheme
,
b
.
drawerTheme
,
t
)!,
...
...
@@ -2273,6 +2287,7 @@ class ThemeData with Diagnosticable {
other
.
checkboxTheme
==
checkboxTheme
&&
other
.
chipTheme
==
chipTheme
&&
other
.
dataTableTheme
==
dataTableTheme
&&
other
.
datePickerTheme
==
datePickerTheme
&&
other
.
dialogTheme
==
dialogTheme
&&
other
.
dividerTheme
==
dividerTheme
&&
other
.
drawerTheme
==
drawerTheme
&&
...
...
@@ -2378,6 +2393,7 @@ class ThemeData with Diagnosticable {
checkboxTheme
,
chipTheme
,
dataTableTheme
,
datePickerTheme
,
dialogTheme
,
dividerTheme
,
drawerTheme
,
...
...
@@ -2485,6 +2501,7 @@ class ThemeData with Diagnosticable {
properties
.
add
(
DiagnosticsProperty
<
CheckboxThemeData
>(
'checkboxTheme'
,
checkboxTheme
,
defaultValue:
defaultData
.
checkboxTheme
,
level:
DiagnosticLevel
.
debug
));
properties
.
add
(
DiagnosticsProperty
<
ChipThemeData
>(
'chipTheme'
,
chipTheme
,
level:
DiagnosticLevel
.
debug
));
properties
.
add
(
DiagnosticsProperty
<
DataTableThemeData
>(
'dataTableTheme'
,
dataTableTheme
,
defaultValue:
defaultData
.
dataTableTheme
,
level:
DiagnosticLevel
.
debug
));
properties
.
add
(
DiagnosticsProperty
<
DatePickerThemeData
>(
'datePickerTheme'
,
datePickerTheme
,
defaultValue:
defaultData
.
datePickerTheme
,
level:
DiagnosticLevel
.
debug
));
properties
.
add
(
DiagnosticsProperty
<
DialogTheme
>(
'dialogTheme'
,
dialogTheme
,
defaultValue:
defaultData
.
dialogTheme
,
level:
DiagnosticLevel
.
debug
));
properties
.
add
(
DiagnosticsProperty
<
DividerThemeData
>(
'dividerTheme'
,
dividerTheme
,
defaultValue:
defaultData
.
dividerTheme
,
level:
DiagnosticLevel
.
debug
));
properties
.
add
(
DiagnosticsProperty
<
DrawerThemeData
>(
'drawerTheme'
,
drawerTheme
,
defaultValue:
defaultData
.
drawerTheme
,
level:
DiagnosticLevel
.
debug
));
...
...
packages/flutter/test/material/date_picker_theme_test.dart
0 → 100644
View file @
198a51ac
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'package:flutter/foundation.dart'
;
import
'package:flutter/material.dart'
;
import
'package:flutter_test/flutter_test.dart'
;
void
main
(
)
{
const
DatePickerThemeData
datePickerTheme
=
DatePickerThemeData
(
backgroundColor:
Color
(
0xfffffff0
),
elevation:
6
,
shadowColor:
Color
(
0xfffffff1
),
surfaceTintColor:
Color
(
0xfffffff2
),
shape:
RoundedRectangleBorder
(),
headerBackgroundColor:
Color
(
0xfffffff3
),
headerForegroundColor:
Color
(
0xfffffff4
),
headerHeadlineStyle:
TextStyle
(
fontSize:
10
),
headerHelpStyle:
TextStyle
(
fontSize:
11
),
weekdayStyle:
TextStyle
(
fontSize:
12
),
dayStyle:
TextStyle
(
fontSize:
13
),
dayForegroundColor:
MaterialStatePropertyAll
<
Color
>(
Color
(
0xfffffff5
)),
dayBackgroundColor:
MaterialStatePropertyAll
<
Color
>(
Color
(
0xfffffff6
)),
dayOverlayColor:
MaterialStatePropertyAll
<
Color
>(
Color
(
0xfffffff7
)),
todayForegroundColor:
MaterialStatePropertyAll
<
Color
>(
Color
(
0xfffffff8
)),
todayBackgroundColor:
MaterialStatePropertyAll
<
Color
>(
Color
(
0xfffffff9
)),
todayBorder:
BorderSide
(
width:
3
),
yearStyle:
TextStyle
(
fontSize:
13
),
yearForegroundColor:
MaterialStatePropertyAll
<
Color
>(
Color
(
0xfffffffa
)),
yearBackgroundColor:
MaterialStatePropertyAll
<
Color
>(
Color
(
0xfffffffb
)),
yearOverlayColor:
MaterialStatePropertyAll
<
Color
>(
Color
(
0xfffffffc
)),
rangePickerBackgroundColor:
Color
(
0xfffffffd
),
rangePickerElevation:
7
,
rangePickerShadowColor:
Color
(
0xfffffffe
),
rangePickerSurfaceTintColor:
Color
(
0xffffffff
),
rangePickerShape:
RoundedRectangleBorder
(),
rangePickerHeaderBackgroundColor:
Color
(
0xffffff0f
),
rangePickerHeaderForegroundColor:
Color
(
0xffffff1f
),
rangePickerHeaderHeadlineStyle:
TextStyle
(
fontSize:
14
),
rangePickerHeaderHelpStyle:
TextStyle
(
fontSize:
15
),
rangeSelectionBackgroundColor:
Color
(
0xffffff2f
),
rangeSelectionOverlayColor:
MaterialStatePropertyAll
<
Color
>(
Color
(
0xffffff3f
)),
);
Material
findDialogMaterial
(
WidgetTester
tester
)
{
return
tester
.
widget
<
Material
>(
find
.
descendant
(
of:
find
.
byType
(
Dialog
),
matching:
find
.
byType
(
Material
)
).
first
);
}
Material
findHeaderMaterial
(
WidgetTester
tester
,
String
text
)
{
return
tester
.
widget
<
Material
>(
find
.
ancestor
(
of:
find
.
text
(
text
),
matching:
find
.
byType
(
Material
)
).
first
,
);
}
BoxDecoration
?
findTextDecoration
(
WidgetTester
tester
,
String
date
)
{
final
Container
container
=
tester
.
widget
<
Container
>(
find
.
ancestor
(
of:
find
.
text
(
date
),
matching:
find
.
byType
(
Container
)
).
first
,
);
return
container
.
decoration
as
BoxDecoration
?;
}
test
(
'DatePickerThemeData copyWith, ==, hashCode basics'
,
()
{
expect
(
const
DatePickerThemeData
(),
const
DatePickerThemeData
().
copyWith
());
expect
(
const
DatePickerThemeData
().
hashCode
,
const
DatePickerThemeData
().
copyWith
().
hashCode
);
});
test
(
'DatePickerThemeData defaults'
,
()
{
const
DatePickerThemeData
theme
=
DatePickerThemeData
();
expect
(
theme
.
backgroundColor
,
null
);
expect
(
theme
.
elevation
,
null
);
expect
(
theme
.
shadowColor
,
null
);
expect
(
theme
.
surfaceTintColor
,
null
);
expect
(
theme
.
shape
,
null
);
expect
(
theme
.
headerBackgroundColor
,
null
);
expect
(
theme
.
headerForegroundColor
,
null
);
expect
(
theme
.
headerHeadlineStyle
,
null
);
expect
(
theme
.
headerHelpStyle
,
null
);
expect
(
theme
.
weekdayStyle
,
null
);
expect
(
theme
.
dayStyle
,
null
);
expect
(
theme
.
dayForegroundColor
,
null
);
expect
(
theme
.
dayBackgroundColor
,
null
);
expect
(
theme
.
dayOverlayColor
,
null
);
expect
(
theme
.
todayForegroundColor
,
null
);
expect
(
theme
.
todayBackgroundColor
,
null
);
expect
(
theme
.
todayBorder
,
null
);
expect
(
theme
.
yearStyle
,
null
);
expect
(
theme
.
yearForegroundColor
,
null
);
expect
(
theme
.
yearBackgroundColor
,
null
);
expect
(
theme
.
yearOverlayColor
,
null
);
expect
(
theme
.
rangePickerBackgroundColor
,
null
);
expect
(
theme
.
rangePickerElevation
,
null
);
expect
(
theme
.
rangePickerShadowColor
,
null
);
expect
(
theme
.
rangePickerSurfaceTintColor
,
null
);
expect
(
theme
.
rangePickerShape
,
null
);
expect
(
theme
.
rangePickerHeaderBackgroundColor
,
null
);
expect
(
theme
.
rangePickerHeaderForegroundColor
,
null
);
expect
(
theme
.
rangePickerHeaderHeadlineStyle
,
null
);
expect
(
theme
.
rangePickerHeaderHelpStyle
,
null
);
expect
(
theme
.
rangeSelectionBackgroundColor
,
null
);
expect
(
theme
.
rangeSelectionOverlayColor
,
null
);
});
testWidgets
(
'DatePickerTheme.defaults M3 defaults'
,
(
WidgetTester
tester
)
async
{
late
final
DatePickerThemeData
m3
;
// M3 Defaults
late
final
ThemeData
theme
;
late
final
ColorScheme
colorScheme
;
late
final
TextTheme
textTheme
;
await
tester
.
pumpWidget
(
MaterialApp
(
theme:
ThemeData
.
light
(
useMaterial3:
true
),
home:
Builder
(
builder:
(
BuildContext
context
)
{
m3
=
DatePickerTheme
.
defaults
(
context
);
theme
=
Theme
.
of
(
context
);
colorScheme
=
theme
.
colorScheme
;
textTheme
=
theme
.
textTheme
;
return
Container
();
},
),
),
);
expect
(
m3
.
backgroundColor
,
colorScheme
.
surface
);
expect
(
m3
.
elevation
,
6
);
expect
(
m3
.
shadowColor
,
const
Color
(
0x00000000
));
// Colors.transparent
expect
(
m3
.
surfaceTintColor
,
colorScheme
.
surfaceTint
);
expect
(
m3
.
shape
,
RoundedRectangleBorder
(
borderRadius:
BorderRadius
.
circular
(
28
)));
expect
(
m3
.
headerBackgroundColor
,
const
Color
(
0x00000000
));
// Colors.transparent
expect
(
m3
.
headerForegroundColor
,
colorScheme
.
onSurfaceVariant
);
expect
(
m3
.
headerHeadlineStyle
,
textTheme
.
headlineLarge
);
expect
(
m3
.
headerHelpStyle
,
textTheme
.
labelMedium
);
expect
(
m3
.
weekdayStyle
,
textTheme
.
bodySmall
?.
apply
(
color:
colorScheme
.
onSurface
));
expect
(
m3
.
dayStyle
,
textTheme
.
bodySmall
);
expect
(
m3
.
dayForegroundColor
?.
resolve
(<
MaterialState
>{}),
colorScheme
.
onSurface
);
expect
(
m3
.
dayForegroundColor
?.
resolve
(<
MaterialState
>{
MaterialState
.
selected
}),
colorScheme
.
onPrimary
);
expect
(
m3
.
dayForegroundColor
?.
resolve
(<
MaterialState
>{
MaterialState
.
disabled
}),
colorScheme
.
onSurface
.
withOpacity
(
0.38
));
expect
(
m3
.
dayBackgroundColor
?.
resolve
(<
MaterialState
>{}),
null
);
expect
(
m3
.
dayBackgroundColor
?.
resolve
(<
MaterialState
>{
MaterialState
.
selected
}),
colorScheme
.
primary
);
expect
(
m3
.
dayOverlayColor
?.
resolve
(<
MaterialState
>{}),
null
);
expect
(
m3
.
dayOverlayColor
?.
resolve
(<
MaterialState
>{
MaterialState
.
selected
,
MaterialState
.
hovered
}),
colorScheme
.
onPrimary
.
withOpacity
(
0.08
));
expect
(
m3
.
dayOverlayColor
?.
resolve
(<
MaterialState
>{
MaterialState
.
selected
,
MaterialState
.
focused
}),
colorScheme
.
onPrimary
.
withOpacity
(
0.12
));
expect
(
m3
.
dayOverlayColor
?.
resolve
(<
MaterialState
>{
MaterialState
.
hovered
}),
colorScheme
.
onSurfaceVariant
.
withOpacity
(
0.08
));
expect
(
m3
.
dayOverlayColor
?.
resolve
(<
MaterialState
>{
MaterialState
.
focused
}),
colorScheme
.
onSurfaceVariant
.
withOpacity
(
0.12
));
expect
(
m3
.
dayOverlayColor
?.
resolve
(<
MaterialState
>{
MaterialState
.
pressed
}),
colorScheme
.
onSurfaceVariant
.
withOpacity
(
0.12
));
expect
(
m3
.
todayForegroundColor
?.
resolve
(<
MaterialState
>{}),
colorScheme
.
primary
);
expect
(
m3
.
todayForegroundColor
?.
resolve
(<
MaterialState
>{
MaterialState
.
disabled
}),
colorScheme
.
primary
.
withOpacity
(
0.38
));
expect
(
m3
.
todayBorder
,
BorderSide
(
color:
colorScheme
.
primary
));
expect
(
m3
.
yearStyle
,
textTheme
.
bodyLarge
);
expect
(
m3
.
yearForegroundColor
?.
resolve
(<
MaterialState
>{}),
colorScheme
.
onSurfaceVariant
);
expect
(
m3
.
yearForegroundColor
?.
resolve
(<
MaterialState
>{
MaterialState
.
selected
}),
colorScheme
.
onPrimary
);
expect
(
m3
.
yearForegroundColor
?.
resolve
(<
MaterialState
>{
MaterialState
.
disabled
}),
colorScheme
.
onSurfaceVariant
.
withOpacity
(
0.38
));
expect
(
m3
.
yearBackgroundColor
?.
resolve
(<
MaterialState
>{}),
null
);
expect
(
m3
.
yearBackgroundColor
?.
resolve
(<
MaterialState
>{
MaterialState
.
selected
}),
colorScheme
.
primary
);
expect
(
m3
.
yearOverlayColor
?.
resolve
(<
MaterialState
>{}),
null
);
expect
(
m3
.
yearOverlayColor
?.
resolve
(<
MaterialState
>{
MaterialState
.
selected
,
MaterialState
.
hovered
}),
colorScheme
.
onPrimary
.
withOpacity
(
0.08
));
expect
(
m3
.
yearOverlayColor
?.
resolve
(<
MaterialState
>{
MaterialState
.
selected
,
MaterialState
.
focused
}),
colorScheme
.
onPrimary
.
withOpacity
(
0.12
));
expect
(
m3
.
yearOverlayColor
?.
resolve
(<
MaterialState
>{
MaterialState
.
hovered
}),
colorScheme
.
onSurfaceVariant
.
withOpacity
(
0.08
));
expect
(
m3
.
yearOverlayColor
?.
resolve
(<
MaterialState
>{
MaterialState
.
focused
}),
colorScheme
.
onSurfaceVariant
.
withOpacity
(
0.12
));
expect
(
m3
.
yearOverlayColor
?.
resolve
(<
MaterialState
>{
MaterialState
.
pressed
}),
colorScheme
.
onSurfaceVariant
.
withOpacity
(
0.12
));
expect
(
m3
.
rangePickerElevation
,
0
);
expect
(
m3
.
rangePickerShape
,
const
RoundedRectangleBorder
());
expect
(
m3
.
rangePickerShadowColor
,
Colors
.
transparent
);
expect
(
m3
.
rangePickerSurfaceTintColor
,
Colors
.
transparent
);
expect
(
m3
.
rangeSelectionOverlayColor
?.
resolve
(<
MaterialState
>{}),
null
);
expect
(
m3
.
rangePickerHeaderBackgroundColor
,
Colors
.
transparent
);
expect
(
m3
.
rangePickerHeaderForegroundColor
,
colorScheme
.
onSurfaceVariant
);
expect
(
m3
.
rangePickerHeaderHeadlineStyle
,
textTheme
.
titleLarge
);
expect
(
m3
.
rangePickerHeaderHelpStyle
,
textTheme
.
titleSmall
);
});
testWidgets
(
'DatePickerTheme.defaults M2 defaults'
,
(
WidgetTester
tester
)
async
{
late
final
DatePickerThemeData
m2
;
// M2 defaults
late
final
ThemeData
theme
;
late
final
ColorScheme
colorScheme
;
late
final
TextTheme
textTheme
;
await
tester
.
pumpWidget
(
MaterialApp
(
theme:
ThemeData
.
light
(
useMaterial3:
false
),
home:
Builder
(
builder:
(
BuildContext
context
)
{
m2
=
DatePickerTheme
.
defaults
(
context
);
theme
=
Theme
.
of
(
context
);
colorScheme
=
theme
.
colorScheme
;
textTheme
=
theme
.
textTheme
;
return
Container
();
},
),
),
);
expect
(
m2
.
elevation
,
24
);
expect
(
m2
.
shape
,
const
RoundedRectangleBorder
(
borderRadius:
BorderRadius
.
all
(
Radius
.
circular
(
4.0
))));
expect
(
m2
.
headerBackgroundColor
,
colorScheme
.
primary
);
expect
(
m2
.
headerForegroundColor
,
colorScheme
.
onPrimary
);
expect
(
m2
.
headerHeadlineStyle
,
textTheme
.
headlineSmall
);
expect
(
m2
.
headerHelpStyle
,
textTheme
.
labelSmall
);
expect
(
m2
.
weekdayStyle
,
textTheme
.
bodySmall
?.
apply
(
color:
colorScheme
.
onSurface
.
withOpacity
(
0.60
)));
expect
(
m2
.
dayStyle
,
textTheme
.
bodySmall
);
expect
(
m2
.
dayForegroundColor
?.
resolve
(<
MaterialState
>{}),
colorScheme
.
onSurface
);
expect
(
m2
.
dayForegroundColor
?.
resolve
(<
MaterialState
>{
MaterialState
.
selected
}),
colorScheme
.
onPrimary
);
expect
(
m2
.
dayForegroundColor
?.
resolve
(<
MaterialState
>{
MaterialState
.
disabled
}),
colorScheme
.
onSurface
.
withOpacity
(
0.38
));
expect
(
m2
.
dayBackgroundColor
?.
resolve
(<
MaterialState
>{}),
null
);
expect
(
m2
.
dayBackgroundColor
?.
resolve
(<
MaterialState
>{
MaterialState
.
selected
}),
colorScheme
.
primary
);
expect
(
m2
.
dayOverlayColor
?.
resolve
(<
MaterialState
>{}),
null
);
expect
(
m2
.
dayOverlayColor
?.
resolve
(<
MaterialState
>{
MaterialState
.
selected
,
MaterialState
.
hovered
}),
colorScheme
.
onPrimary
.
withOpacity
(
0.08
));
expect
(
m2
.
dayOverlayColor
?.
resolve
(<
MaterialState
>{
MaterialState
.
selected
,
MaterialState
.
focused
}),
colorScheme
.
onPrimary
.
withOpacity
(
0.12
));
expect
(
m2
.
dayOverlayColor
?.
resolve
(<
MaterialState
>{
MaterialState
.
selected
,
MaterialState
.
pressed
}),
colorScheme
.
onPrimary
.
withOpacity
(
0.38
));
expect
(
m2
.
dayOverlayColor
?.
resolve
(<
MaterialState
>{
MaterialState
.
hovered
}),
colorScheme
.
onSurfaceVariant
.
withOpacity
(
0.08
));
expect
(
m2
.
dayOverlayColor
?.
resolve
(<
MaterialState
>{
MaterialState
.
focused
}),
colorScheme
.
onSurfaceVariant
.
withOpacity
(
0.12
));
expect
(
m2
.
dayOverlayColor
?.
resolve
(<
MaterialState
>{
MaterialState
.
pressed
}),
colorScheme
.
onSurfaceVariant
.
withOpacity
(
0.12
));
expect
(
m2
.
todayForegroundColor
?.
resolve
(<
MaterialState
>{}),
colorScheme
.
primary
);
expect
(
m2
.
todayForegroundColor
?.
resolve
(<
MaterialState
>{
MaterialState
.
disabled
}),
colorScheme
.
onSurface
.
withOpacity
(
0.38
));
expect
(
m2
.
todayBorder
,
BorderSide
(
color:
colorScheme
.
primary
));
expect
(
m2
.
yearStyle
,
textTheme
.
bodyLarge
);
expect
(
m2
.
rangePickerBackgroundColor
,
colorScheme
.
surface
);
expect
(
m2
.
rangePickerElevation
,
0
);
expect
(
m2
.
rangePickerShape
,
const
RoundedRectangleBorder
());
expect
(
m2
.
rangePickerShadowColor
,
Colors
.
transparent
);
expect
(
m2
.
rangePickerSurfaceTintColor
,
Colors
.
transparent
);
expect
(
m2
.
rangeSelectionOverlayColor
?.
resolve
(<
MaterialState
>{}),
null
);
expect
(
m2
.
rangeSelectionOverlayColor
?.
resolve
(<
MaterialState
>{
MaterialState
.
selected
,
MaterialState
.
hovered
}),
colorScheme
.
onPrimary
.
withOpacity
(
0.08
));
expect
(
m2
.
rangeSelectionOverlayColor
?.
resolve
(<
MaterialState
>{
MaterialState
.
selected
,
MaterialState
.
focused
}),
colorScheme
.
onPrimary
.
withOpacity
(
0.12
));
expect
(
m2
.
rangeSelectionOverlayColor
?.
resolve
(<
MaterialState
>{
MaterialState
.
selected
,
MaterialState
.
pressed
}),
colorScheme
.
onPrimary
.
withOpacity
(
0.38
));
expect
(
m2
.
rangeSelectionOverlayColor
?.
resolve
(<
MaterialState
>{
MaterialState
.
hovered
}),
colorScheme
.
onSurfaceVariant
.
withOpacity
(
0.08
));
expect
(
m2
.
rangeSelectionOverlayColor
?.
resolve
(<
MaterialState
>{
MaterialState
.
focused
}),
colorScheme
.
onSurfaceVariant
.
withOpacity
(
0.12
));
expect
(
m2
.
rangeSelectionOverlayColor
?.
resolve
(<
MaterialState
>{
MaterialState
.
pressed
}),
colorScheme
.
onSurfaceVariant
.
withOpacity
(
0.12
));
expect
(
m2
.
rangePickerHeaderBackgroundColor
,
colorScheme
.
primary
);
expect
(
m2
.
rangePickerHeaderForegroundColor
,
colorScheme
.
onPrimary
);
expect
(
m2
.
rangePickerHeaderHeadlineStyle
,
textTheme
.
headlineSmall
);
expect
(
m2
.
rangePickerHeaderHelpStyle
,
textTheme
.
labelSmall
);
});
testWidgets
(
'Default DatePickerThemeData debugFillProperties'
,
(
WidgetTester
tester
)
async
{
final
DiagnosticPropertiesBuilder
builder
=
DiagnosticPropertiesBuilder
();
const
DatePickerThemeData
().
debugFillProperties
(
builder
);
final
List
<
String
>
description
=
builder
.
properties
.
where
((
DiagnosticsNode
node
)
=>
!
node
.
isFiltered
(
DiagnosticLevel
.
info
))
.
map
((
DiagnosticsNode
node
)
=>
node
.
toString
())
.
toList
();
expect
(
description
,
<
String
>[]);
});
testWidgets
(
'DatePickerThemeData implements debugFillProperties'
,
(
WidgetTester
tester
)
async
{
final
DiagnosticPropertiesBuilder
builder
=
DiagnosticPropertiesBuilder
();
datePickerTheme
.
debugFillProperties
(
builder
);
final
List
<
String
>
description
=
builder
.
properties
.
where
((
DiagnosticsNode
node
)
=>
!
node
.
isFiltered
(
DiagnosticLevel
.
info
))
.
map
((
DiagnosticsNode
node
)
=>
node
.
toString
())
.
toList
();
expect
(
description
,
<
String
>[
'backgroundColor: Color(0xfffffff0)'
,
'elevation: 6.0'
,
'shadowColor: Color(0xfffffff1)'
,
'surfaceTintColor: Color(0xfffffff2)'
,
'shape: RoundedRectangleBorder(BorderSide(width: 0.0, style: none), BorderRadius.zero)'
,
'headerBackgroundColor: Color(0xfffffff3)'
,
'headerForegroundColor: Color(0xfffffff4)'
,
'headerHeadlineStyle: TextStyle(inherit: true, size: 10.0)'
,
'headerHelpStyle: TextStyle(inherit: true, size: 11.0)'
,
'weekDayStyle: TextStyle(inherit: true, size: 12.0)'
,
'dayStyle: TextStyle(inherit: true, size: 13.0)'
,
'dayForegroundColor: MaterialStatePropertyAll(Color(0xfffffff5))'
,
'dayBackgroundColor: MaterialStatePropertyAll(Color(0xfffffff6))'
,
'dayOverlayColor: MaterialStatePropertyAll(Color(0xfffffff7))'
,
'todayForegroundColor: MaterialStatePropertyAll(Color(0xfffffff8))'
,
'todayBackgroundColor: MaterialStatePropertyAll(Color(0xfffffff9))'
,
'todayBorder: BorderSide(width: 3.0)'
,
'yearStyle: TextStyle(inherit: true, size: 13.0)'
,
'yearForegroundColor: MaterialStatePropertyAll(Color(0xfffffffa))'
,
'yearBackgroundColor: MaterialStatePropertyAll(Color(0xfffffffb))'
,
'yearOverlayColor: MaterialStatePropertyAll(Color(0xfffffffc))'
,
'rangePickerBackgroundColor: Color(0xfffffffd)'
,
'rangePickerElevation: 7.0'
,
'rangePickerShadowColor: Color(0xfffffffe)'
,
'rangePickerSurfaceTintColor: Color(0xffffffff)'
,
'rangePickerShape: RoundedRectangleBorder(BorderSide(width: 0.0, style: none), BorderRadius.zero)'
,
'rangePickerHeaderBackgroundColor: Color(0xffffff0f)'
,
'rangePickerHeaderForegroundColor: Color(0xffffff1f)'
,
'rangePickerHeaderHeadlineStyle: TextStyle(inherit: true, size: 14.0)'
,
'rangePickerHeaderHelpStyle: TextStyle(inherit: true, size: 15.0)'
,
'rangeSelectionBackgroundColor: Color(0xffffff2f)'
,
'rangeSelectionOverlayColor: MaterialStatePropertyAll(Color(0xffffff3f))'
,
]);
});
testWidgets
(
'DatePickerDialog uses ThemeData datePicker theme'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
MaterialApp
(
theme:
ThemeData
.
light
(
useMaterial3:
true
).
copyWith
(
datePickerTheme:
datePickerTheme
,
),
home:
Directionality
(
textDirection:
TextDirection
.
ltr
,
child:
Material
(
child:
Center
(
child:
DatePickerDialog
(
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
Text
weekday
=
tester
.
widget
<
Text
>(
find
.
text
(
'W'
));
expect
(
weekday
.
style
?.
color
,
datePickerTheme
.
weekdayStyle
?.
color
);
expect
(
weekday
.
style
?.
fontSize
,
datePickerTheme
.
weekdayStyle
?.
fontSize
);
final
Text
selectedDate
=
tester
.
widget
<
Text
>(
find
.
text
(
'Wed, Jan 25'
));
expect
(
selectedDate
.
style
?.
color
,
datePickerTheme
.
headerForegroundColor
);
expect
(
selectedDate
.
style
?.
fontSize
,
datePickerTheme
.
headerHeadlineStyle
?.
fontSize
);
final
Text
day31
=
tester
.
widget
<
Text
>(
find
.
text
(
'31'
));
final
BoxDecoration
day31Decoration
=
findTextDecoration
(
tester
,
'31'
)!;
expect
(
day31
.
style
?.
color
,
datePickerTheme
.
dayForegroundColor
?.
resolve
(<
MaterialState
>{}));
expect
(
day31
.
style
?.
fontSize
,
datePickerTheme
.
dayStyle
?.
fontSize
);
expect
(
day31Decoration
.
color
,
datePickerTheme
.
dayBackgroundColor
?.
resolve
(<
MaterialState
>{}));
final
Text
day24
=
tester
.
widget
<
Text
>(
find
.
text
(
'24'
));
// DatePickerDialog.currentDate
final
BoxDecoration
day24Decoration
=
findTextDecoration
(
tester
,
'24'
)!;
expect
(
day24
.
style
?.
fontSize
,
datePickerTheme
.
dayStyle
?.
fontSize
);
expect
(
day24
.
style
?.
color
,
datePickerTheme
.
todayForegroundColor
?.
resolve
(<
MaterialState
>{}));
expect
(
day24Decoration
.
color
,
datePickerTheme
.
todayBackgroundColor
?.
resolve
(<
MaterialState
>{}));
expect
(
day24Decoration
.
border
?.
top
.
width
,
datePickerTheme
.
todayBorder
?.
width
);
expect
(
day24Decoration
.
border
?.
bottom
.
width
,
datePickerTheme
.
todayBorder
?.
width
);
// Show the year selector.
await
tester
.
tap
(
find
.
text
(
'January 2023'
));
await
tester
.
pumpAndSettle
();
final
Text
year2022
=
tester
.
widget
<
Text
>(
find
.
text
(
'2022'
));
final
BoxDecoration
year2022Decoration
=
findTextDecoration
(
tester
,
'2022'
)!;
expect
(
year2022
.
style
?.
fontSize
,
datePickerTheme
.
yearStyle
?.
fontSize
);
expect
(
year2022
.
style
?.
color
,
datePickerTheme
.
yearForegroundColor
?.
resolve
(<
MaterialState
>{}));
expect
(
year2022Decoration
.
color
,
datePickerTheme
.
yearBackgroundColor
?.
resolve
(<
MaterialState
>{}));
final
Text
year2023
=
tester
.
widget
<
Text
>(
find
.
text
(
'2023'
));
// DatePickerDialog.currentDate
final
BoxDecoration
year2023Decoration
=
findTextDecoration
(
tester
,
'2023'
)!;
expect
(
year2023
.
style
?.
fontSize
,
datePickerTheme
.
yearStyle
?.
fontSize
);
expect
(
year2023
.
style
?.
color
,
datePickerTheme
.
todayForegroundColor
?.
resolve
(<
MaterialState
>{}));
expect
(
year2023Decoration
.
color
,
datePickerTheme
.
todayBackgroundColor
?.
resolve
(<
MaterialState
>{}));
expect
(
year2023Decoration
.
border
?.
top
.
width
,
datePickerTheme
.
todayBorder
?.
width
);
expect
(
year2023Decoration
.
border
?.
bottom
.
width
,
datePickerTheme
.
todayBorder
?.
width
);
expect
(
year2023Decoration
.
border
?.
top
.
color
,
datePickerTheme
.
todayForegroundColor
?.
resolve
(<
MaterialState
>{}));
expect
(
year2023Decoration
.
border
?.
bottom
.
color
,
datePickerTheme
.
todayForegroundColor
?.
resolve
(<
MaterialState
>{}));
});
testWidgets
(
'DateRangePickerDialog uses ThemeData datePicker theme'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
MaterialApp
(
theme:
ThemeData
.
light
(
useMaterial3:
true
).
copyWith
(
datePickerTheme:
datePickerTheme
,
),
home:
Directionality
(
textDirection:
TextDirection
.
ltr
,
child:
Material
(
child:
Center
(
child:
DateRangePickerDialog
(
firstDate:
DateTime
(
2023
),
lastDate:
DateTime
(
2023
,
DateTime
.
january
,
31
),
initialDateRange:
DateTimeRange
(
start:
DateTime
(
2023
,
DateTime
.
january
,
17
),
end:
DateTime
(
2023
,
DateTime
.
january
,
20
),
),
currentDate:
DateTime
(
2023
,
DateTime
.
january
,
23
),
),
),
),
),
),
);
final
Material
material
=
findDialogMaterial
(
tester
);
expect
(
material
.
color
,
datePickerTheme
.
backgroundColor
);
//!!
expect
(
tester
.
widget
<
Scaffold
>(
find
.
byType
(
Scaffold
)).
backgroundColor
,
datePickerTheme
.
rangePickerBackgroundColor
);
expect
(
material
.
elevation
,
datePickerTheme
.
rangePickerElevation
);
expect
(
material
.
shadowColor
,
datePickerTheme
.
rangePickerShadowColor
);
expect
(
material
.
surfaceTintColor
,
datePickerTheme
.
rangePickerSurfaceTintColor
);
expect
(
material
.
shape
,
datePickerTheme
.
rangePickerShape
);
final
Text
selectRange
=
tester
.
widget
<
Text
>(
find
.
text
(
'Select range'
));
expect
(
selectRange
.
style
?.
color
,
datePickerTheme
.
rangePickerHeaderForegroundColor
);
expect
(
selectRange
.
style
?.
fontSize
,
datePickerTheme
.
rangePickerHeaderHelpStyle
?.
fontSize
);
final
Text
selectedDate
=
tester
.
widget
<
Text
>(
find
.
text
(
'Jan 17'
));
expect
(
selectedDate
.
style
?.
color
,
datePickerTheme
.
rangePickerHeaderForegroundColor
);
expect
(
selectedDate
.
style
?.
fontSize
,
datePickerTheme
.
rangePickerHeaderHeadlineStyle
?.
fontSize
);
});
}
packages/flutter/test/material/theme_data_test.dart
View file @
198a51ac
...
...
@@ -781,6 +781,7 @@ void main() {
checkboxTheme:
const
CheckboxThemeData
(),
chipTheme:
chipTheme
,
dataTableTheme:
const
DataTableThemeData
(),
datePickerTheme:
const
DatePickerThemeData
(),
dialogTheme:
const
DialogTheme
(
backgroundColor:
Colors
.
black
),
dividerTheme:
const
DividerThemeData
(
color:
Colors
.
black
),
drawerTheme:
const
DrawerThemeData
(),
...
...
@@ -901,6 +902,7 @@ void main() {
checkboxTheme:
const
CheckboxThemeData
(),
chipTheme:
otherChipTheme
,
dataTableTheme:
const
DataTableThemeData
(),
datePickerTheme:
const
DatePickerThemeData
(
backgroundColor:
Colors
.
amber
),
dialogTheme:
const
DialogTheme
(
backgroundColor:
Colors
.
white
),
dividerTheme:
const
DividerThemeData
(
color:
Colors
.
white
),
drawerTheme:
const
DrawerThemeData
(),
...
...
@@ -1008,6 +1010,7 @@ void main() {
chipTheme:
otherTheme
.
chipTheme
,
dataTableTheme:
otherTheme
.
dataTableTheme
,
dialogTheme:
otherTheme
.
dialogTheme
,
datePickerTheme:
otherTheme
.
datePickerTheme
,
dividerTheme:
otherTheme
.
dividerTheme
,
drawerTheme:
otherTheme
.
drawerTheme
,
elevatedButtonTheme:
otherTheme
.
elevatedButtonTheme
,
...
...
@@ -1110,6 +1113,7 @@ void main() {
expect
(
themeDataCopy
.
checkboxTheme
,
equals
(
otherTheme
.
checkboxTheme
));
expect
(
themeDataCopy
.
chipTheme
,
equals
(
otherTheme
.
chipTheme
));
expect
(
themeDataCopy
.
dataTableTheme
,
equals
(
otherTheme
.
dataTableTheme
));
expect
(
themeDataCopy
.
datePickerTheme
,
equals
(
otherTheme
.
datePickerTheme
));
expect
(
themeDataCopy
.
dialogTheme
,
equals
(
otherTheme
.
dialogTheme
));
expect
(
themeDataCopy
.
dividerTheme
,
equals
(
otherTheme
.
dividerTheme
));
expect
(
themeDataCopy
.
drawerTheme
,
equals
(
otherTheme
.
drawerTheme
));
...
...
@@ -1248,6 +1252,7 @@ void main() {
'checkboxTheme'
,
'chipTheme'
,
'dataTableTheme'
,
'datePickerTheme'
,
'dialogTheme'
,
'dividerTheme'
,
'drawerTheme'
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment