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
e58ee0fb
Unverified
Commit
e58ee0fb
authored
Mar 22, 2021
by
Shi-Hao Hong
Committed by
GitHub
Mar 22, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[State Restoration] Material DateRangePicker, adds some general state restoration tests (#78506)
parent
2977a346
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
652 additions
and
63 deletions
+652
-63
date_picker.dart
packages/flutter/lib/src/material/date_picker.dart
+287
-47
restoration_properties.dart
packages/flutter/lib/src/widgets/restoration_properties.dart
+28
-0
date_picker_test.dart
packages/flutter/test/material/date_picker_test.dart
+8
-3
date_range_picker_test.dart
packages/flutter/test/material/date_range_picker_test.dart
+194
-0
restorable_property_test.dart
packages/flutter/test/widgets/restorable_property_test.dart
+135
-13
No files found.
packages/flutter/lib/src/material/date_picker.dart
View file @
e58ee0fb
...
...
@@ -901,14 +901,14 @@ class _DatePickerHeader extends StatelessWidget {
/// returned.
///
/// If [initialDateRange] is non-null, then it will be used as the initially
/// selected date range. If it is provided,
[initialDateRange.start]
must be
/// before or on
[initialDateRange.end]
.
/// selected date range. If it is provided,
`initialDateRange.start`
must be
/// before or on
`initialDateRange.end`
.
///
/// The [firstDate] is the earliest allowable date. The [lastDate] is the latest
/// allowable date. Both must be non-null.
///
/// If an initial date range is provided,
[initialDateRange.start]
/// and
[initialDateRange.end]
must both fall between or on [firstDate] and
/// If an initial date range is provided,
`initialDateRange.start`
/// and
`initialDateRange.end`
must both fall between or on [firstDate] and
/// [lastDate]. For all of these [DateTime] values, only their dates are
/// considered. Their time fields are ignored.
///
...
...
@@ -958,6 +958,133 @@ class _DatePickerHeader extends StatelessWidget {
/// The [builder] parameter can be used to wrap the dialog widget
/// to add inherited widgets like [Theme].
///
/// ### State Restoration
///
/// Using this method will not enable state restoration for the date range picker.
/// In order to enable state restoration for a date range picker, use
/// [Navigator.restorablePush] or [Navigator.restorablePushNamed] with
/// [DateRangePickerDialog].
///
/// For more information about state restoration, see [RestorationManager].
///
/// {@macro flutter.widgets.RestorationManager}
///
/// {@tool sample --template=freeform}
///
/// This sample demonstrates how to create a restorable Material date range picker.
/// This is accomplished by enabling state restoration by specifying
/// [MaterialApp.restorationScopeId] and using [Navigator.restorablePush] to
/// push [DateRangePickerDialog] when the button is tapped.
///
/// ```dart imports
/// import 'package:flutter/material.dart';
/// ```
///
/// ```dart
/// void main() {
/// runApp(const MyApp());
/// }
///
/// class MyApp extends StatelessWidget {
/// const MyApp({Key? key}) : super(key: key);
///
/// @override
/// Widget build(BuildContext context) {
/// return const MaterialApp(
/// restorationScopeId: 'app',
/// title: 'Restorable Date Range Picker Demo',
/// home: MyHomePage(),
/// );
/// }
/// }
///
/// class MyHomePage extends StatefulWidget {
/// const MyHomePage({Key? key}) : super(key: key);
///
/// @override
/// _MyHomePageState createState() => _MyHomePageState();
/// }
///
/// class _MyHomePageState extends State<MyHomePage> with RestorationMixin {
/// final RestorableDateTimeN _startDate = RestorableDateTimeN(DateTime(2021, 1, 1));
/// final RestorableDateTimeN _endDate = RestorableDateTimeN(DateTime(2021, 1, 5));
/// late final RestorableRouteFuture<DateTimeRange?> _restorableDateRangePickerRouteFuture = RestorableRouteFuture<DateTimeRange?>(
/// onComplete: _selectDateRange,
/// onPresent: (NavigatorState navigator, Object? arguments) {
/// return navigator.restorablePush(
/// _dateRangePickerRoute,
/// arguments: <String, dynamic>{
/// 'initialStartDate': _startDate.value?.millisecondsSinceEpoch,
/// 'initialEndDate': _endDate.value?.millisecondsSinceEpoch,
/// }
/// );
/// },
/// );
///
/// void _selectDateRange(DateTimeRange? newSelectedDate) {
/// if (newSelectedDate != null) {
/// setState(() {
/// _startDate.value = newSelectedDate.start;
/// _endDate.value = newSelectedDate.end;
/// });
/// }
/// }
///
/// @override
/// String get restorationId => 'scaffold_state';
///
/// @override
/// void restoreState(RestorationBucket? oldBucket, bool initialRestore) {
/// registerForRestoration(_startDate, 'start_date');
/// registerForRestoration(_endDate, 'end_date');
/// registerForRestoration(_restorableDateRangePickerRouteFuture, 'date_picker_route_future');
/// }
///
/// static Route<DateTimeRange?> _dateRangePickerRoute(
/// BuildContext context,
/// Object? arguments,
/// ) {
/// return DialogRoute<DateTimeRange?>(
/// context: context,
/// builder: (BuildContext context) {
/// return DateRangePickerDialog(
/// restorationId: 'date_picker_dialog',
/// initialDateRange: _initialDateTimeRange(arguments! as Map<dynamic, dynamic>),
/// firstDate: DateTime(2021, 1, 1),
/// currentDate: DateTime(2021, 1, 25),
/// lastDate: DateTime(2022, 1, 1),
/// );
/// },
/// );
/// }
///
/// static DateTimeRange? _initialDateTimeRange(Map<dynamic, dynamic> arguments) {
/// if (arguments['initialStartDate'] != null && arguments['initialEndDate'] != null) {
/// return DateTimeRange(
/// start: DateTime.fromMillisecondsSinceEpoch(arguments['initialStartDate'] as int),
/// end: DateTime.fromMillisecondsSinceEpoch(arguments['initialEndDate'] as int),
/// );
/// }
///
/// return null;
/// }
///
/// @override
/// Widget build(BuildContext context) {
/// return Scaffold(
/// body: Center(
/// child: OutlinedButton(
/// onPressed: () { _restorableDateRangePickerRouteFuture.present(); },
/// child: const Text('Open Date Range Picker'),
/// ),
/// ),
/// );
/// }
/// }
/// ```
///
/// {@end-tool}
///
/// See also:
///
/// * [showDatePicker], which shows a material design date picker used to
...
...
@@ -1027,7 +1154,7 @@ Future<DateTimeRange?> showDateRangePicker({
assert
(
useRootNavigator
!=
null
);
assert
(
debugCheckHasMaterialLocalizations
(
context
));
Widget
dialog
=
_
DateRangePickerDialog
(
Widget
dialog
=
DateRangePickerDialog
(
initialDateRange:
initialDateRange
,
firstDate:
firstDate
,
lastDate:
lastDate
,
...
...
@@ -1100,8 +1227,18 @@ String _formatRangeEndDate(MaterialLocalizations localizations, DateTime? startD
:
localizations
.
formatShortDate
(
endDate
);
}
class
_DateRangePickerDialog
extends
StatefulWidget
{
const
_DateRangePickerDialog
({
/// A Material-style date range picker dialog.
///
/// It is used internally by [showDateRangePicker] or can be directly pushed
/// onto the [Navigator] stack to enable state restoration. See
/// [showDateRangePicker] for a state restoration app example.
///
/// See also:
///
/// * [showDateRangePicker], which is a way to display the date picker.
class
DateRangePickerDialog
extends
StatefulWidget
{
/// A Material-style date range picker dialog.
const
DateRangePickerDialog
({
Key
?
key
,
this
.
initialDateRange
,
required
this
.
firstDate
,
...
...
@@ -1119,58 +1256,161 @@ class _DateRangePickerDialog extends StatefulWidget {
this
.
fieldEndHintText
,
this
.
fieldStartLabelText
,
this
.
fieldEndLabelText
,
this
.
restorationId
,
})
:
super
(
key:
key
);
/// The date range that the date range picker starts with when it opens.
///
/// If an initial date range is provided, `initialDateRange.start`
/// and `initialDateRange.end` must both fall between or on [firstDate] and
/// [lastDate]. For all of these [DateTime] values, only their dates are
/// considered. Their time fields are ignored.
///
/// If [initialDateRange] is non-null, then it will be used as the initially
/// selected date range. If it is provided, `initialDateRange.start` must be
/// before or on `initialDateRange.end`.
final
DateTimeRange
?
initialDateRange
;
/// The earliest allowable date on the date range.
final
DateTime
firstDate
;
/// The latest allowable date on the date range.
final
DateTime
lastDate
;
/// The [currentDate] represents the current day (i.e. today).
///
/// This date will be highlighted in the day grid.
///
/// If `null`, the date of `DateTime.now()` will be used.
final
DateTime
?
currentDate
;
/// The initial date range picker entry mode.
///
/// The date range has two main modes: [DatePickerEntryMode.calendar] (a
/// scrollable calendar month grid) or [DatePickerEntryMode.input] (two text
/// input fields) mode.
///
/// It defaults to [DatePickerEntryMode.calendar] and must be non-null.
final
DatePickerEntryMode
initialEntryMode
;
/// The label on the cancel button for the text input mode.
///
/// If null, the localized value of
/// [MaterialLocalizations.cancelButtonLabel] is used.
final
String
?
cancelText
;
/// The label on the "OK" button for the text input mode.
///
/// If null, the localized value of
/// [MaterialLocalizations.okButtonLabel] is used.
final
String
?
confirmText
;
/// The label on the save button for the fullscreen calendar mode.
///
/// If null, the localized value of
/// [MaterialLocalizations.saveButtonLabel] is used.
final
String
?
saveText
;
/// The label displayed at the top of the dialog.
///
/// If null, the localized value of
/// [MaterialLocalizations.dateRangePickerHelpText] is used.
final
String
?
helpText
;
/// The message used when the date range is invalid (e.g. start date is after
/// end date).
///
/// If null, the localized value of
/// [MaterialLocalizations.invalidDateRangeLabel] is used.
final
String
?
errorInvalidRangeText
;
/// The message used when an input text isn't in a proper date format.
///
/// If null, the localized value of
/// [MaterialLocalizations.invalidDateFormatLabel] is used.
final
String
?
errorFormatText
;
/// The message used when an input text isn't a selectable date.
///
/// If null, the localized value of
/// [MaterialLocalizations.dateOutOfRangeLabel] is used.
final
String
?
errorInvalidText
;
/// The text used to prompt the user when no text has been entered in the
/// start field.
///
/// If null, the localized value of
/// [MaterialLocalizations.dateHelpText] is used.
final
String
?
fieldStartHintText
;
/// The text used to prompt the user when no text has been entered in the
/// end field.
///
/// If null, the localized value of [MaterialLocalizations.dateHelpText] is
/// used.
final
String
?
fieldEndHintText
;
/// The label for the start date text input field.
///
/// If null, the localized value of [MaterialLocalizations.dateRangeStartLabel]
/// is used.
final
String
?
fieldStartLabelText
;
/// The label for the end date text input field.
///
/// If null, the localized value of [MaterialLocalizations.dateRangeEndLabel]
/// is used.
final
String
?
fieldEndLabelText
;
/// Restoration ID to save and restore the state of the [DateRangePickerDialog].
///
/// If it is non-null, the date range picker will persist and restore the
/// date range selected on the dialog.
///
/// The state of this widget is persisted in a [RestorationBucket] claimed
/// from the surrounding [RestorationScope] using the provided restoration ID.
///
/// See also:
///
/// * [RestorationManager], which explains how state restoration works in
/// Flutter.
final
String
?
restorationId
;
@override
_DateRangePickerDialogState
createState
()
=>
_DateRangePickerDialogState
();
}
class
_DateRangePickerDialogState
extends
State
<
_DateRangePickerDialog
>
{
late
DatePickerEntryMode
_entryMode
;
DateTime
?
_selectedStart
;
DateTime
?
_selectedEnd
;
late
bool
_autoValidate
;
class
_DateRangePickerDialogState
extends
State
<
DateRangePickerDialog
>
with
RestorationMixin
{
late
final
_RestorableDatePickerEntryMode
_entryMode
=
_RestorableDatePickerEntryMode
(
widget
.
initialEntryMode
)
;
late
final
RestorableDateTimeN
_selectedStart
=
RestorableDateTimeN
(
widget
.
initialDateRange
?.
start
)
;
late
final
RestorableDateTimeN
_selectedEnd
=
RestorableDateTimeN
(
widget
.
initialDateRange
?.
end
)
;
final
RestorableBool
_autoValidate
=
RestorableBool
(
false
)
;
final
GlobalKey
_calendarPickerKey
=
GlobalKey
();
final
GlobalKey
<
_InputDateRangePickerState
>
_inputPickerKey
=
GlobalKey
<
_InputDateRangePickerState
>();
@override
void
initState
()
{
super
.
initState
();
_selectedStart
=
widget
.
initialDateRange
?.
start
;
_selectedEnd
=
widget
.
initialDateRange
?.
end
;
_entryMode
=
widget
.
initialEntryMode
;
_autoValidate
=
false
;
String
?
get
restorationId
=>
widget
.
restorationId
;
@override
void
restoreState
(
RestorationBucket
?
oldBucket
,
bool
initialRestore
)
{
registerForRestoration
(
_entryMode
,
'entry_mode'
);
registerForRestoration
(
_selectedStart
,
'selected_start'
);
registerForRestoration
(
_selectedEnd
,
'selected_end'
);
registerForRestoration
(
_autoValidate
,
'autovalidate'
);
}
void
_handleOk
()
{
if
(
_entryMode
==
DatePickerEntryMode
.
input
||
_entryMod
e
==
DatePickerEntryMode
.
inputOnly
)
{
if
(
_entryMode
.
value
==
DatePickerEntryMode
.
input
||
_entryMode
.
valu
e
==
DatePickerEntryMode
.
inputOnly
)
{
final
_InputDateRangePickerState
picker
=
_inputPickerKey
.
currentState
!;
if
(!
picker
.
validate
())
{
setState
(()
{
_autoValidate
=
true
;
_autoValidate
.
value
=
true
;
});
return
;
}
}
final
DateTimeRange
?
selectedRange
=
_hasSelectedDateRange
?
DateTimeRange
(
start:
_selectedStart
!,
end:
_selectedEnd
!)
?
DateTimeRange
(
start:
_selectedStart
.
value
!,
end:
_selectedEnd
.
value
!)
:
null
;
Navigator
.
pop
(
context
,
selectedRange
);
...
...
@@ -1182,29 +1422,29 @@ class _DateRangePickerDialogState extends State<_DateRangePickerDialog> {
void
_handleEntryModeToggle
()
{
setState
(()
{
switch
(
_entryMode
)
{
switch
(
_entryMode
.
value
)
{
case
DatePickerEntryMode
.
calendar
:
_autoValidate
=
false
;
_entryMode
=
DatePickerEntryMode
.
input
;
_autoValidate
.
value
=
false
;
_entryMode
.
value
=
DatePickerEntryMode
.
input
;
break
;
case
DatePickerEntryMode
.
input
:
// Validate the range dates
if
(
_selectedStart
!=
null
&&
(
_selectedStart
!.
isBefore
(
widget
.
firstDate
)
||
_selectedStart
!.
isAfter
(
widget
.
lastDate
)))
{
_selectedStart
=
null
;
if
(
_selectedStart
.
value
!=
null
&&
(
_selectedStart
.
value
!.
isBefore
(
widget
.
firstDate
)
||
_selectedStart
.
value
!.
isAfter
(
widget
.
lastDate
)))
{
_selectedStart
.
value
=
null
;
// With no valid start date, having an end date makes no sense for the UI.
_selectedEnd
=
null
;
_selectedEnd
.
value
=
null
;
}
if
(
_selectedEnd
!=
null
&&
(
_selectedEnd
!.
isBefore
(
widget
.
firstDate
)
||
_selectedEnd
!.
isAfter
(
widget
.
lastDate
)))
{
_selectedEnd
=
null
;
if
(
_selectedEnd
.
value
!=
null
&&
(
_selectedEnd
.
value
!.
isBefore
(
widget
.
firstDate
)
||
_selectedEnd
.
value
!.
isAfter
(
widget
.
lastDate
)))
{
_selectedEnd
.
value
=
null
;
}
// If invalid range (start after end), then just use the start date
if
(
_selectedStart
!=
null
&&
_selectedEnd
!=
null
&&
_selectedStart
!.
isAfter
(
_selectedEnd
!))
{
_selectedEnd
=
null
;
if
(
_selectedStart
.
value
!=
null
&&
_selectedEnd
.
value
!=
null
&&
_selectedStart
.
value
!.
isAfter
(
_selectedEnd
.
value
!))
{
_selectedEnd
.
value
=
null
;
}
_entryMode
=
DatePickerEntryMode
.
calendar
;
_entryMode
.
value
=
DatePickerEntryMode
.
calendar
;
break
;
case
DatePickerEntryMode
.
calendarOnly
:
...
...
@@ -1216,14 +1456,14 @@ class _DateRangePickerDialogState extends State<_DateRangePickerDialog> {
}
void
_handleStartDateChanged
(
DateTime
?
date
)
{
setState
(()
=>
_selectedStart
=
date
);
setState
(()
=>
_selectedStart
.
value
=
date
);
}
void
_handleEndDateChanged
(
DateTime
?
date
)
{
setState
(()
=>
_selectedEnd
=
date
);
setState
(()
=>
_selectedEnd
.
value
=
date
);
}
bool
get
_hasSelectedDateRange
=>
_selectedStart
!=
null
&&
_selectedEnd
!=
null
;
bool
get
_hasSelectedDateRange
=>
_selectedStart
.
value
!=
null
&&
_selectedEnd
.
value
!=
null
;
@override
Widget
build
(
BuildContext
context
)
{
...
...
@@ -1242,15 +1482,15 @@ class _DateRangePickerDialogState extends State<_DateRangePickerDialog> {
final
double
elevation
;
final
EdgeInsets
insetPadding
;
final
bool
showEntryModeButton
=
_entryMode
==
DatePickerEntryMode
.
calendar
||
_entryMode
==
DatePickerEntryMode
.
input
;
switch
(
_entryMode
)
{
_entryMode
.
value
==
DatePickerEntryMode
.
calendar
||
_entryMode
.
value
==
DatePickerEntryMode
.
input
;
switch
(
_entryMode
.
value
)
{
case
DatePickerEntryMode
.
calendar
:
case
DatePickerEntryMode
.
calendarOnly
:
contents
=
_CalendarRangePickerDialog
(
key:
_calendarPickerKey
,
selectedStartDate:
_selectedStart
,
selectedEndDate:
_selectedEnd
,
selectedStartDate:
_selectedStart
.
value
,
selectedEndDate:
_selectedEnd
.
value
,
firstDate:
widget
.
firstDate
,
lastDate:
widget
.
lastDate
,
currentDate:
widget
.
currentDate
,
...
...
@@ -1279,8 +1519,8 @@ class _DateRangePickerDialogState extends State<_DateRangePickerDialog> {
case
DatePickerEntryMode
.
input
:
case
DatePickerEntryMode
.
inputOnly
:
contents
=
_InputDateRangePickerDialog
(
selectedStartDate:
_selectedStart
,
selectedEndDate:
_selectedEnd
,
selectedStartDate:
_selectedStart
.
value
,
selectedEndDate:
_selectedEnd
.
value
,
currentDate:
widget
.
currentDate
,
picker:
Container
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
24
),
...
...
@@ -1292,14 +1532,14 @@ class _DateRangePickerDialogState extends State<_DateRangePickerDialog> {
const
Spacer
(),
_InputDateRangePicker
(
key:
_inputPickerKey
,
initialStartDate:
_selectedStart
,
initialEndDate:
_selectedEnd
,
initialStartDate:
_selectedStart
.
value
,
initialEndDate:
_selectedEnd
.
value
,
firstDate:
widget
.
firstDate
,
lastDate:
widget
.
lastDate
,
onStartDateChanged:
_handleStartDateChanged
,
onEndDateChanged:
_handleEndDateChanged
,
autofocus:
true
,
autovalidate:
_autoValidate
,
autovalidate:
_autoValidate
.
value
,
helpText:
widget
.
helpText
,
errorInvalidRangeText:
widget
.
errorInvalidRangeText
,
errorFormatText:
widget
.
errorFormatText
,
...
...
packages/flutter/lib/src/widgets/restoration_properties.dart
View file @
e58ee0fb
...
...
@@ -385,6 +385,34 @@ class RestorableDateTime extends RestorableValue<DateTime> {
Object
?
toPrimitives
()
=>
value
.
millisecondsSinceEpoch
;
}
/// A [RestorableValue] that knows how to save and restore [DateTime] that is
/// nullable.
///
/// {@macro flutter.widgets.RestorableNum}.
class
RestorableDateTimeN
extends
RestorableValue
<
DateTime
?>
{
/// Creates a [RestorableDateTime].
///
/// {@macro flutter.widgets.RestorableNum.constructor}
RestorableDateTimeN
(
DateTime
?
defaultValue
)
:
_defaultValue
=
defaultValue
;
final
DateTime
?
_defaultValue
;
@override
DateTime
?
createDefaultValue
()
=>
_defaultValue
;
@override
void
didUpdateValue
(
DateTime
?
oldValue
)
{
assert
(
debugIsSerializableForRestoration
(
value
?.
millisecondsSinceEpoch
));
notifyListeners
();
}
@override
DateTime
?
fromPrimitives
(
Object
?
data
)
=>
data
!=
null
?
DateTime
.
fromMillisecondsSinceEpoch
(
data
as
int
)
:
null
;
@override
Object
?
toPrimitives
()
=>
value
?.
millisecondsSinceEpoch
;
}
/// A base class for creating a [RestorableProperty] that stores and restores a
/// [Listenable].
///
...
...
packages/flutter/test/material/date_picker_test.dart
View file @
e58ee0fb
...
...
@@ -1162,9 +1162,14 @@ void main() {
await
tester
.
restoreFrom
(
restorationData
);
expect
(
find
.
byType
(
DatePickerDialog
),
findsOneWidget
);
// Select a different date
and close the date picker
.
// Select a different date.
await
tester
.
tap
(
find
.
text
(
'30'
));
await
tester
.
pumpAndSettle
();
// Restart after the new selection. It should remain selected.
await
tester
.
restartAndRestore
();
// Close the date picker.
await
tester
.
tap
(
find
.
text
(
'OK'
));
await
tester
.
pumpAndSettle
();
...
...
@@ -1210,8 +1215,8 @@ void main() {
await
tester
.
tapAt
(
const
Offset
(
10.0
,
10.0
));
await
tester
.
pumpAndSettle
();
// The date picker should be closed, the text value
updated to th
e
//
newly selected dat
e.
// The date picker should be closed, the text value
should be the sam
e
//
as befor
e.
expect
(
find
.
byType
(
DatePickerDialog
),
findsNothing
);
expect
(
find
.
text
(
'25/7/2021'
),
findsOneWidget
);
...
...
packages/flutter/test/material/date_range_picker_test.dart
View file @
e58ee0fb
...
...
@@ -853,4 +853,198 @@ void main() {
_testInputDecorator
(
tester
.
widget
(
borderContainers
.
last
),
border
,
Colors
.
transparent
);
});
});
testWidgets
(
'DatePickerDialog is state restorable'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
const
MaterialApp
(
restorationScopeId:
'app'
,
home:
_RestorableDateRangePickerDialogTestWidget
(),
),
);
// The date range picker should be closed.
expect
(
find
.
byType
(
DateRangePickerDialog
),
findsNothing
);
expect
(
find
.
text
(
'1/1/2021 to 5/1/2021'
),
findsOneWidget
);
// Open the date range picker.
await
tester
.
tap
(
find
.
text
(
'X'
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
byType
(
DateRangePickerDialog
),
findsOneWidget
);
final
TestRestorationData
restorationData
=
await
tester
.
getRestorationData
();
await
tester
.
restartAndRestore
();
// The date range picker should be open after restoring.
expect
(
find
.
byType
(
DateRangePickerDialog
),
findsOneWidget
);
// Close the date range picker.
await
tester
.
tap
(
find
.
byIcon
(
Icons
.
close
));
await
tester
.
pumpAndSettle
();
// The date range picker should be closed, the text value updated to the
// newly selected date.
expect
(
find
.
byType
(
DateRangePickerDialog
),
findsNothing
);
expect
(
find
.
text
(
'1/1/2021 to 5/1/2021'
),
findsOneWidget
);
// The date range picker should be open after restoring.
await
tester
.
restoreFrom
(
restorationData
);
expect
(
find
.
byType
(
DateRangePickerDialog
),
findsOneWidget
);
// // Select a different date and close the date range picker.
await
tester
.
tap
(
find
.
text
(
'12'
).
first
);
await
tester
.
pumpAndSettle
();
await
tester
.
tap
(
find
.
text
(
'14'
).
first
);
await
tester
.
pumpAndSettle
();
// Restart after the new selection. It should remain selected.
await
tester
.
restartAndRestore
();
// Close the date range picker.
await
tester
.
tap
(
find
.
text
(
'SAVE'
));
await
tester
.
pumpAndSettle
();
// The date range picker should be closed, the text value updated to the
// newly selected date.
expect
(
find
.
byType
(
DateRangePickerDialog
),
findsNothing
);
expect
(
find
.
text
(
'12/1/2021 to 14/1/2021'
),
findsOneWidget
);
},
skip:
isBrowser
);
// https://github.com/flutter/flutter/issues/33615
testWidgets
(
'DateRangePickerDialog state restoration - DatePickerEntryMode'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
const
MaterialApp
(
restorationScopeId:
'app'
,
home:
_RestorableDateRangePickerDialogTestWidget
(
datePickerEntryMode:
DatePickerEntryMode
.
calendarOnly
,
),
),
);
// The date range picker should be closed.
expect
(
find
.
byType
(
DateRangePickerDialog
),
findsNothing
);
expect
(
find
.
text
(
'1/1/2021 to 5/1/2021'
),
findsOneWidget
);
// Open the date range picker.
await
tester
.
tap
(
find
.
text
(
'X'
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
byType
(
DateRangePickerDialog
),
findsOneWidget
);
// Only in calendar mode and cannot switch out.
expect
(
find
.
byType
(
TextField
),
findsNothing
);
expect
(
find
.
byIcon
(
Icons
.
edit
),
findsNothing
);
final
TestRestorationData
restorationData
=
await
tester
.
getRestorationData
();
await
tester
.
restartAndRestore
();
// The date range picker should be open after restoring.
expect
(
find
.
byType
(
DateRangePickerDialog
),
findsOneWidget
);
// Only in calendar mode and cannot switch out.
expect
(
find
.
byType
(
TextField
),
findsNothing
);
expect
(
find
.
byIcon
(
Icons
.
edit
),
findsNothing
);
// Tap on the barrier.
await
tester
.
tap
(
find
.
byIcon
(
Icons
.
close
));
await
tester
.
pumpAndSettle
();
// The date range picker should be closed, the text value should be the same
// as before.
expect
(
find
.
byType
(
DateRangePickerDialog
),
findsNothing
);
expect
(
find
.
text
(
'1/1/2021 to 5/1/2021'
),
findsOneWidget
);
// The date range picker should be open after restoring.
await
tester
.
restoreFrom
(
restorationData
);
expect
(
find
.
byType
(
DateRangePickerDialog
),
findsOneWidget
);
// Only in calendar mode and cannot switch out.
expect
(
find
.
byType
(
TextField
),
findsNothing
);
expect
(
find
.
byIcon
(
Icons
.
edit
),
findsNothing
);
},
skip:
isBrowser
);
// https://github.com/flutter/flutter/issues/33615
}
class
_RestorableDateRangePickerDialogTestWidget
extends
StatefulWidget
{
const
_RestorableDateRangePickerDialogTestWidget
({
Key
?
key
,
this
.
datePickerEntryMode
=
DatePickerEntryMode
.
calendar
,
})
:
super
(
key:
key
);
final
DatePickerEntryMode
datePickerEntryMode
;
@override
_RestorableDateRangePickerDialogTestWidgetState
createState
()
=>
_RestorableDateRangePickerDialogTestWidgetState
();
}
class
_RestorableDateRangePickerDialogTestWidgetState
extends
State
<
_RestorableDateRangePickerDialogTestWidget
>
with
RestorationMixin
{
@override
String
?
get
restorationId
=>
'scaffold_state'
;
final
RestorableDateTimeN
_startDate
=
RestorableDateTimeN
(
DateTime
(
2021
,
1
,
1
));
final
RestorableDateTimeN
_endDate
=
RestorableDateTimeN
(
DateTime
(
2021
,
1
,
5
));
late
final
RestorableRouteFuture
<
DateTimeRange
?>
_restorableDateRangePickerRouteFuture
=
RestorableRouteFuture
<
DateTimeRange
?>(
onComplete:
_selectDateRange
,
onPresent:
(
NavigatorState
navigator
,
Object
?
arguments
)
{
return
navigator
.
restorablePush
(
_dateRangePickerRoute
,
arguments:
<
String
,
dynamic
>{
'datePickerEntryMode'
:
widget
.
datePickerEntryMode
.
index
,
}
);
},
);
@override
void
restoreState
(
RestorationBucket
?
oldBucket
,
bool
initialRestore
)
{
registerForRestoration
(
_startDate
,
'start_date'
);
registerForRestoration
(
_endDate
,
'end_date'
);
registerForRestoration
(
_restorableDateRangePickerRouteFuture
,
'date_picker_route_future'
);
}
void
_selectDateRange
(
DateTimeRange
?
newSelectedDate
)
{
if
(
newSelectedDate
!=
null
)
{
setState
(()
{
_startDate
.
value
=
newSelectedDate
.
start
;
_endDate
.
value
=
newSelectedDate
.
end
;
});
}
}
static
Route
<
DateTimeRange
?>
_dateRangePickerRoute
(
BuildContext
context
,
Object
?
arguments
,
)
{
return
DialogRoute
<
DateTimeRange
?>(
context:
context
,
builder:
(
BuildContext
context
)
{
final
Map
<
dynamic
,
dynamic
>
args
=
arguments
!
as
Map
<
dynamic
,
dynamic
>;
return
DateRangePickerDialog
(
restorationId:
'date_picker_dialog'
,
initialEntryMode:
DatePickerEntryMode
.
values
[
args
[
'datePickerEntryMode'
]
as
int
],
firstDate:
DateTime
(
2021
,
1
,
1
),
currentDate:
DateTime
(
2021
,
1
,
25
),
lastDate:
DateTime
(
2022
,
1
,
1
),
);
},
);
}
@override
Widget
build
(
BuildContext
context
)
{
final
DateTime
?
startDateTime
=
_startDate
.
value
;
final
DateTime
?
endDateTime
=
_endDate
.
value
;
// Example: "25/7/1994"
final
String
startDateTimeString
=
'
${startDateTime?.day}
/
${startDateTime?.month}
/
${startDateTime?.year}
'
;
final
String
endDateTimeString
=
'
${endDateTime?.day}
/
${endDateTime?.month}
/
${endDateTime?.year}
'
;
return
Scaffold
(
body:
Center
(
child:
Column
(
children:
<
Widget
>[
OutlinedButton
(
onPressed:
()
{
_restorableDateRangePickerRouteFuture
.
present
();
},
child:
const
Text
(
'X'
),
),
Text
(
'
$startDateTimeString
to
$endDateTimeString
'
),
],
),
),
);
}
}
packages/flutter/test/widgets/restorable_property_test.dart
View file @
e58ee0fb
...
...
@@ -19,6 +19,7 @@ void main() {
expect
(()
=>
RestorableBoolN
(
true
).
value
,
throwsAssertionError
);
expect
(()
=>
RestorableTextEditingController
().
value
,
throwsAssertionError
);
expect
(()
=>
RestorableDateTime
(
DateTime
(
2020
,
4
,
3
)).
value
,
throwsAssertionError
);
expect
(()
=>
RestorableDateTimeN
(
DateTime
(
2020
,
4
,
3
)).
value
,
throwsAssertionError
);
expect
(()
=>
_TestRestorableValue
().
value
,
throwsAssertionError
);
});
...
...
@@ -34,8 +35,14 @@ void main() {
expect
(
state
.
intValue
.
value
,
42
);
expect
(
state
.
stringValue
.
value
,
'hello world'
);
expect
(
state
.
boolValue
.
value
,
false
);
expect
(
state
.
controllerValue
.
value
.
text
,
'FooBar'
);
expect
(
state
.
dateTimeValue
.
value
,
DateTime
(
2021
,
3
,
16
));
expect
(
state
.
nullableNumValue
.
value
,
null
);
expect
(
state
.
nullableDoubleValue
.
value
,
null
);
expect
(
state
.
nullableIntValue
.
value
,
null
);
expect
(
state
.
nullableStringValue
.
value
,
null
);
expect
(
state
.
nullableBoolValue
.
value
,
null
);
expect
(
state
.
nullableDateTimeValue
.
value
,
null
);
expect
(
state
.
controllerValue
.
value
.
text
,
'FooBar'
);
expect
(
state
.
objectValue
.
value
,
55
);
// Modify values.
...
...
@@ -45,8 +52,14 @@ void main() {
state
.
intValue
.
value
=
10
;
state
.
stringValue
.
value
=
'guten tag'
;
state
.
boolValue
.
value
=
true
;
state
.
controllerValue
.
value
.
text
=
'blabla'
;
state
.
dateTimeValue
.
value
=
DateTime
(
2020
,
7
,
4
);
state
.
nullableNumValue
.
value
=
5.0
;
state
.
nullableDoubleValue
.
value
=
2.0
;
state
.
nullableIntValue
.
value
=
1
;
state
.
nullableStringValue
.
value
=
'hullo'
;
state
.
nullableBoolValue
.
value
=
false
;
state
.
nullableDateTimeValue
.
value
=
DateTime
(
2020
,
4
,
4
);
state
.
controllerValue
.
value
.
text
=
'blabla'
;
state
.
objectValue
.
value
=
53
;
});
await
tester
.
pump
();
...
...
@@ -56,8 +69,14 @@ void main() {
expect
(
state
.
intValue
.
value
,
10
);
expect
(
state
.
stringValue
.
value
,
'guten tag'
);
expect
(
state
.
boolValue
.
value
,
true
);
expect
(
state
.
controllerValue
.
value
.
text
,
'blabla'
);
expect
(
state
.
dateTimeValue
.
value
,
DateTime
(
2020
,
7
,
4
));
expect
(
state
.
nullableNumValue
.
value
,
5.0
);
expect
(
state
.
nullableDoubleValue
.
value
,
2.0
);
expect
(
state
.
nullableIntValue
.
value
,
1
);
expect
(
state
.
nullableStringValue
.
value
,
'hullo'
);
expect
(
state
.
nullableBoolValue
.
value
,
false
);
expect
(
state
.
nullableDateTimeValue
.
value
,
DateTime
(
2020
,
4
,
4
));
expect
(
state
.
controllerValue
.
value
.
text
,
'blabla'
);
expect
(
state
.
objectValue
.
value
,
53
);
expect
(
find
.
text
(
'guten tag'
),
findsOneWidget
);
});
...
...
@@ -77,8 +96,14 @@ void main() {
expect
(
state
.
intValue
.
value
,
42
);
expect
(
state
.
stringValue
.
value
,
'hello world'
);
expect
(
state
.
boolValue
.
value
,
false
);
expect
(
state
.
controllerValue
.
value
.
text
,
'FooBar'
);
expect
(
state
.
dateTimeValue
.
value
,
DateTime
(
2021
,
3
,
16
));
expect
(
state
.
nullableNumValue
.
value
,
null
);
expect
(
state
.
nullableDoubleValue
.
value
,
null
);
expect
(
state
.
nullableIntValue
.
value
,
null
);
expect
(
state
.
nullableStringValue
.
value
,
null
);
expect
(
state
.
nullableBoolValue
.
value
,
null
);
expect
(
state
.
nullableDateTimeValue
.
value
,
null
);
expect
(
state
.
controllerValue
.
value
.
text
,
'FooBar'
);
expect
(
state
.
objectValue
.
value
,
55
);
// Modify values.
...
...
@@ -88,8 +113,14 @@ void main() {
state
.
intValue
.
value
=
10
;
state
.
stringValue
.
value
=
'guten tag'
;
state
.
boolValue
.
value
=
true
;
state
.
controllerValue
.
value
.
text
=
'blabla'
;
state
.
dateTimeValue
.
value
=
DateTime
(
2020
,
7
,
4
);
state
.
nullableNumValue
.
value
=
5.0
;
state
.
nullableDoubleValue
.
value
=
2.0
;
state
.
nullableIntValue
.
value
=
1
;
state
.
nullableStringValue
.
value
=
'hullo'
;
state
.
nullableBoolValue
.
value
=
false
;
state
.
nullableDateTimeValue
.
value
=
DateTime
(
2020
,
4
,
4
);
state
.
controllerValue
.
value
.
text
=
'blabla'
;
state
.
objectValue
.
value
=
53
;
});
await
tester
.
pump
();
...
...
@@ -99,8 +130,14 @@ void main() {
expect
(
state
.
intValue
.
value
,
10
);
expect
(
state
.
stringValue
.
value
,
'guten tag'
);
expect
(
state
.
boolValue
.
value
,
true
);
expect
(
state
.
controllerValue
.
value
.
text
,
'blabla'
);
expect
(
state
.
dateTimeValue
.
value
,
DateTime
(
2020
,
7
,
4
));
expect
(
state
.
nullableNumValue
.
value
,
5.0
);
expect
(
state
.
nullableDoubleValue
.
value
,
2.0
);
expect
(
state
.
nullableIntValue
.
value
,
1
);
expect
(
state
.
nullableStringValue
.
value
,
'hullo'
);
expect
(
state
.
nullableBoolValue
.
value
,
false
);
expect
(
state
.
nullableDateTimeValue
.
value
,
DateTime
(
2020
,
4
,
4
));
expect
(
state
.
controllerValue
.
value
.
text
,
'blabla'
);
expect
(
state
.
objectValue
.
value
,
53
);
expect
(
find
.
text
(
'guten tag'
),
findsOneWidget
);
...
...
@@ -115,8 +152,14 @@ void main() {
expect
(
state
.
intValue
.
value
,
10
);
expect
(
state
.
stringValue
.
value
,
'guten tag'
);
expect
(
state
.
boolValue
.
value
,
true
);
expect
(
state
.
controllerValue
.
value
.
text
,
'blabla'
);
expect
(
state
.
dateTimeValue
.
value
,
DateTime
(
2020
,
7
,
4
));
expect
(
state
.
nullableNumValue
.
value
,
5.0
);
expect
(
state
.
nullableDoubleValue
.
value
,
2.0
);
expect
(
state
.
nullableIntValue
.
value
,
1
);
expect
(
state
.
nullableStringValue
.
value
,
'hullo'
);
expect
(
state
.
nullableBoolValue
.
value
,
false
);
expect
(
state
.
nullableDateTimeValue
.
value
,
DateTime
(
2020
,
4
,
4
));
expect
(
state
.
controllerValue
.
value
.
text
,
'blabla'
);
expect
(
state
.
objectValue
.
value
,
53
);
expect
(
find
.
text
(
'guten tag'
),
findsOneWidget
);
});
...
...
@@ -137,13 +180,14 @@ void main() {
state
.
intValue
.
value
=
10
;
state
.
stringValue
.
value
=
'guten tag'
;
state
.
boolValue
.
value
=
true
;
state
.
dateTimeValue
.
value
=
DateTime
(
2020
,
7
,
4
);
state
.
nullableNumValue
.
value
=
5.0
;
state
.
nullableDoubleValue
.
value
=
2.0
;
state
.
nullableIntValue
.
value
=
1
;
state
.
nullableStringValue
.
value
=
'hullo'
;
state
.
nullableBoolValue
.
value
=
false
;
state
.
nullableDateTimeValue
.
value
=
DateTime
(
2020
,
4
,
4
);
state
.
controllerValue
.
value
.
text
=
'blabla'
;
state
.
dateTimeValue
.
value
=
DateTime
(
2020
,
7
,
4
);
state
.
objectValue
.
value
=
53
;
});
await
tester
.
pump
();
...
...
@@ -158,13 +202,14 @@ void main() {
state
.
intValue
.
value
=
20
;
state
.
stringValue
.
value
=
'ciao'
;
state
.
boolValue
.
value
=
false
;
state
.
dateTimeValue
.
value
=
DateTime
(
2020
,
3
,
2
);
state
.
nullableNumValue
.
value
=
20.0
;
state
.
nullableDoubleValue
.
value
=
20.0
;
state
.
nullableIntValue
.
value
=
20
;
state
.
nullableStringValue
.
value
=
'ni hao'
;
state
.
nullableBoolValue
.
value
=
null
;
state
.
nullableDateTimeValue
.
value
=
DateTime
(
2020
,
5
,
5
);
state
.
controllerValue
.
value
.
text
=
'blub'
;
state
.
dateTimeValue
.
value
=
DateTime
(
2020
,
3
,
2
);
state
.
objectValue
.
value
=
20
;
});
await
tester
.
pump
();
...
...
@@ -178,13 +223,14 @@ void main() {
expect
(
state
.
intValue
.
value
,
10
);
expect
(
state
.
stringValue
.
value
,
'guten tag'
);
expect
(
state
.
boolValue
.
value
,
true
);
expect
(
state
.
dateTimeValue
.
value
,
DateTime
(
2020
,
7
,
4
));
expect
(
state
.
nullableNumValue
.
value
,
5.0
);
expect
(
state
.
nullableDoubleValue
.
value
,
2.0
);
expect
(
state
.
nullableIntValue
.
value
,
1
);
expect
(
state
.
nullableStringValue
.
value
,
'hullo'
);
expect
(
state
.
nullableBoolValue
.
value
,
false
);
expect
(
state
.
nullableDateTimeValue
.
value
,
DateTime
(
2020
,
4
,
4
));
expect
(
state
.
controllerValue
.
value
.
text
,
'blabla'
);
expect
(
state
.
dateTimeValue
.
value
,
DateTime
(
2020
,
7
,
4
));
expect
(
state
.
objectValue
.
value
,
53
);
expect
(
find
.
text
(
'guten tag'
),
findsOneWidget
);
expect
(
state
.
controllerValue
.
value
,
isNot
(
same
(
controller
)));
...
...
@@ -196,13 +242,14 @@ void main() {
expect
(
state
.
intValue
.
value
,
42
);
expect
(
state
.
stringValue
.
value
,
'hello world'
);
expect
(
state
.
boolValue
.
value
,
false
);
expect
(
state
.
dateTimeValue
.
value
,
DateTime
(
2021
,
3
,
16
));
expect
(
state
.
nullableNumValue
.
value
,
null
);
expect
(
state
.
nullableDoubleValue
.
value
,
null
);
expect
(
state
.
nullableIntValue
.
value
,
null
);
expect
(
state
.
nullableStringValue
.
value
,
null
);
expect
(
state
.
nullableBoolValue
.
value
,
null
);
expect
(
state
.
nullableDateTimeValue
.
value
,
null
);
expect
(
state
.
controllerValue
.
value
.
text
,
'FooBar'
);
expect
(
state
.
dateTimeValue
.
value
,
DateTime
(
2021
,
3
,
16
));
expect
(
state
.
objectValue
.
value
,
55
);
expect
(
find
.
text
(
'hello world'
),
findsOneWidget
);
});
...
...
@@ -217,6 +264,7 @@ void main() {
final
_RestorableWidgetState
state
=
tester
.
state
(
find
.
byType
(
_RestorableWidget
));
final
List
<
String
>
notifyLog
=
<
String
>[];
state
.
numValue
.
addListener
(()
{
notifyLog
.
add
(
'num'
);
});
...
...
@@ -232,6 +280,27 @@ void main() {
state
.
boolValue
.
addListener
(()
{
notifyLog
.
add
(
'bool'
);
});
state
.
dateTimeValue
.
addListener
(()
{
notifyLog
.
add
(
'date-time'
);
});
state
.
nullableNumValue
.
addListener
(()
{
notifyLog
.
add
(
'nullable-num'
);
});
state
.
nullableDoubleValue
.
addListener
(()
{
notifyLog
.
add
(
'nullable-double'
);
});
state
.
nullableIntValue
.
addListener
(()
{
notifyLog
.
add
(
'nullable-int'
);
});
state
.
nullableStringValue
.
addListener
(()
{
notifyLog
.
add
(
'nullable-string'
);
});
state
.
nullableBoolValue
.
addListener
(()
{
notifyLog
.
add
(
'nullable-bool'
);
});
state
.
nullableDateTimeValue
.
addListener
(()
{
notifyLog
.
add
(
'nullable-date-time'
);
});
state
.
controllerValue
.
addListener
(()
{
notifyLog
.
add
(
'controller'
);
});
...
...
@@ -269,6 +338,48 @@ void main() {
expect
(
notifyLog
.
single
,
'bool'
);
notifyLog
.
clear
();
state
.
setProperties
(()
{
state
.
dateTimeValue
.
value
=
DateTime
(
2020
,
7
,
4
);
});
expect
(
notifyLog
.
single
,
'date-time'
);
notifyLog
.
clear
();
state
.
setProperties
(()
{
state
.
nullableNumValue
.
value
=
42.2
;
});
expect
(
notifyLog
.
single
,
'nullable-num'
);
notifyLog
.
clear
();
state
.
setProperties
(()
{
state
.
nullableDoubleValue
.
value
=
42.2
;
});
expect
(
notifyLog
.
single
,
'nullable-double'
);
notifyLog
.
clear
();
state
.
setProperties
(()
{
state
.
nullableIntValue
.
value
=
45
;
});
expect
(
notifyLog
.
single
,
'nullable-int'
);
notifyLog
.
clear
();
state
.
setProperties
(()
{
state
.
nullableStringValue
.
value
=
'bar'
;
});
expect
(
notifyLog
.
single
,
'nullable-string'
);
notifyLog
.
clear
();
state
.
setProperties
(()
{
state
.
nullableBoolValue
.
value
=
true
;
});
expect
(
notifyLog
.
single
,
'nullable-bool'
);
notifyLog
.
clear
();
state
.
setProperties
(()
{
state
.
nullableDateTimeValue
.
value
=
DateTime
(
2020
,
4
,
4
);
});
expect
(
notifyLog
.
single
,
'nullable-date-time'
);
notifyLog
.
clear
();
state
.
setProperties
(()
{
state
.
controllerValue
.
value
.
text
=
'foo'
;
});
...
...
@@ -291,8 +402,17 @@ void main() {
state
.
intValue
.
value
=
45
;
state
.
stringValue
.
value
=
'bar'
;
state
.
boolValue
.
value
=
true
;
state
.
dateTimeValue
.
value
=
DateTime
(
2020
,
7
,
4
);
state
.
nullableNumValue
.
value
=
42.2
;
state
.
nullableDoubleValue
.
value
=
42.2
;
state
.
nullableIntValue
.
value
=
45
;
state
.
nullableStringValue
.
value
=
'bar'
;
state
.
nullableBoolValue
.
value
=
true
;
state
.
nullableDateTimeValue
.
value
=
DateTime
(
2020
,
4
,
4
);
state
.
controllerValue
.
value
.
text
=
'foo'
;
state
.
objectValue
.
value
=
42
;
});
expect
(
notifyLog
,
isEmpty
);
});
...
...
@@ -396,13 +516,14 @@ class _RestorableWidgetState extends State<_RestorableWidget> with RestorationMi
final
RestorableInt
intValue
=
RestorableInt
(
42
);
final
RestorableString
stringValue
=
RestorableString
(
'hello world'
);
final
RestorableBool
boolValue
=
RestorableBool
(
false
);
final
RestorableDateTime
dateTimeValue
=
RestorableDateTime
(
DateTime
(
2021
,
3
,
16
));
final
RestorableNumN
<
num
?>
nullableNumValue
=
RestorableNumN
<
num
?>(
null
);
final
RestorableDoubleN
nullableDoubleValue
=
RestorableDoubleN
(
null
);
final
RestorableIntN
nullableIntValue
=
RestorableIntN
(
null
);
final
RestorableStringN
nullableStringValue
=
RestorableStringN
(
null
);
final
RestorableBoolN
nullableBoolValue
=
RestorableBoolN
(
null
);
final
RestorableDateTimeN
nullableDateTimeValue
=
RestorableDateTimeN
(
null
);
final
RestorableTextEditingController
controllerValue
=
RestorableTextEditingController
(
text:
'FooBar'
);
final
RestorableDateTime
dateTimeValue
=
RestorableDateTime
(
DateTime
(
2021
,
3
,
16
));
final
_TestRestorableValue
objectValue
=
_TestRestorableValue
();
@override
...
...
@@ -412,13 +533,14 @@ class _RestorableWidgetState extends State<_RestorableWidget> with RestorationMi
registerForRestoration
(
intValue
,
'int'
);
registerForRestoration
(
stringValue
,
'string'
);
registerForRestoration
(
boolValue
,
'bool'
);
registerForRestoration
(
dateTimeValue
,
'dateTime'
);
registerForRestoration
(
nullableNumValue
,
'nullableNum'
);
registerForRestoration
(
nullableDoubleValue
,
'nullableDouble'
);
registerForRestoration
(
nullableIntValue
,
'nullableInt'
);
registerForRestoration
(
nullableStringValue
,
'nullableString'
);
registerForRestoration
(
nullableBoolValue
,
'nullableBool'
);
registerForRestoration
(
nullableDateTimeValue
,
'nullableDateTime'
);
registerForRestoration
(
controllerValue
,
'controller'
);
registerForRestoration
(
dateTimeValue
,
'dateTime'
);
registerForRestoration
(
objectValue
,
'object'
);
}
...
...
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