mirror of
https://github.com/flutter/flutter
synced 2024-10-02 14:34:22 +00:00
Add selectionOverlayBuilder in CupertinoDatePicker and CupertinoTimer… (#143079)
It's now possible to override the default selection overlay with CupertinoDatePicker.selectionOverlayBuilder and CupertinoTimerPicker.selectionOverlayBuilder.
This commit is contained in:
parent
980b5a1976
commit
e2e68c047c
|
@ -70,6 +70,10 @@ const Widget _startSelectionOverlay = CupertinoPickerDefaultSelectionOverlay(cap
|
||||||
const Widget _centerSelectionOverlay = CupertinoPickerDefaultSelectionOverlay(capStartEdge: false, capEndEdge: false);
|
const Widget _centerSelectionOverlay = CupertinoPickerDefaultSelectionOverlay(capStartEdge: false, capEndEdge: false);
|
||||||
const Widget _endSelectionOverlay = CupertinoPickerDefaultSelectionOverlay(capStartEdge: false);
|
const Widget _endSelectionOverlay = CupertinoPickerDefaultSelectionOverlay(capStartEdge: false);
|
||||||
|
|
||||||
|
/// Defines a function signature for creating a widget that serves as a selection overlay,
|
||||||
|
/// given the current context, the selected item's index, and the total number of columns.
|
||||||
|
typedef SelectionOverlayBuilder = Widget? Function(BuildContext context, { required int columnCount, required int selectedIndex });
|
||||||
|
|
||||||
// Lays out the date picker based on how much space each single column needs.
|
// Lays out the date picker based on how much space each single column needs.
|
||||||
//
|
//
|
||||||
// Each column is a child of this delegate, indexed from 0 to number of columns - 1.
|
// Each column is a child of this delegate, indexed from 0 to number of columns - 1.
|
||||||
|
@ -291,6 +295,7 @@ class CupertinoDatePicker extends StatefulWidget {
|
||||||
this.backgroundColor,
|
this.backgroundColor,
|
||||||
this.showDayOfWeek = false,
|
this.showDayOfWeek = false,
|
||||||
this.itemExtent = _kItemExtent,
|
this.itemExtent = _kItemExtent,
|
||||||
|
this.selectionOverlayBuilder,
|
||||||
}) : initialDateTime = initialDateTime ?? DateTime.now(),
|
}) : initialDateTime = initialDateTime ?? DateTime.now(),
|
||||||
assert(
|
assert(
|
||||||
itemExtent > 0,
|
itemExtent > 0,
|
||||||
|
@ -413,6 +418,48 @@ class CupertinoDatePicker extends StatefulWidget {
|
||||||
/// Defaults to a value that matches the default iOS date picker wheel.
|
/// Defaults to a value that matches the default iOS date picker wheel.
|
||||||
final double itemExtent;
|
final double itemExtent;
|
||||||
|
|
||||||
|
/// A function that returns a widget that is overlaid on the picker
|
||||||
|
/// to highlight the currently selected entry.
|
||||||
|
///
|
||||||
|
/// If unspecified, it defaults to a [CupertinoPickerDefaultSelectionOverlay]
|
||||||
|
/// which is a gray rounded rectangle overlay in iOS 14 style.
|
||||||
|
///
|
||||||
|
/// If the selection overlay builder returns null, no overlay will be drawn.
|
||||||
|
///
|
||||||
|
/// {@tool snippet}
|
||||||
|
///
|
||||||
|
/// This example shows how to recreate the default selection overlay
|
||||||
|
/// with selectionOverlayBuilder.
|
||||||
|
///
|
||||||
|
/// ```dart
|
||||||
|
/// CupertinoDatePicker(
|
||||||
|
/// onDateTimeChanged: (DateTime newDateTime) {},
|
||||||
|
/// mode: CupertinoDatePickerMode.date,
|
||||||
|
/// initialDateTime: DateTime(2018, 9, 15),
|
||||||
|
/// selectionOverlayBuilder: (
|
||||||
|
/// BuildContext context, {
|
||||||
|
/// required int selectedIndex,
|
||||||
|
/// required int columnCount,
|
||||||
|
/// }) {
|
||||||
|
/// if (selectedIndex == 0) {
|
||||||
|
/// return const CupertinoPickerDefaultSelectionOverlay(
|
||||||
|
/// capEndEdge: false,
|
||||||
|
/// );
|
||||||
|
/// } else if (selectedIndex == columnCount - 1) {
|
||||||
|
/// return const CupertinoPickerDefaultSelectionOverlay(
|
||||||
|
/// capStartEdge: false,
|
||||||
|
/// );
|
||||||
|
/// }
|
||||||
|
/// return const CupertinoPickerDefaultSelectionOverlay(
|
||||||
|
/// capStartEdge: false,
|
||||||
|
/// capEndEdge: false,
|
||||||
|
/// );
|
||||||
|
/// },
|
||||||
|
/// )
|
||||||
|
/// ```
|
||||||
|
/// {@end-tool}
|
||||||
|
final SelectionOverlayBuilder? selectionOverlayBuilder;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<StatefulWidget> createState() {
|
State<StatefulWidget> createState() {
|
||||||
// ignore: no_logic_in_create_state, https://github.com/flutter/flutter/issues/70499
|
// ignore: no_logic_in_create_state, https://github.com/flutter/flutter/issues/70499
|
||||||
|
@ -511,7 +558,7 @@ class CupertinoDatePicker extends StatefulWidget {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef _ColumnBuilder = Widget Function(double offAxisFraction, TransitionBuilder itemPositioningBuilder, Widget selectionOverlay);
|
typedef _ColumnBuilder = Widget Function(double offAxisFraction, TransitionBuilder itemPositioningBuilder, Widget? selectionOverlay);
|
||||||
|
|
||||||
class _CupertinoDatePickerDateTimeState extends State<CupertinoDatePicker> {
|
class _CupertinoDatePickerDateTimeState extends State<CupertinoDatePicker> {
|
||||||
// Fraction of the farthest column's vanishing point vs its width. Eyeballed
|
// Fraction of the farthest column's vanishing point vs its width. Eyeballed
|
||||||
|
@ -716,7 +763,7 @@ class _CupertinoDatePickerDateTimeState extends State<CupertinoDatePicker> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Builds the date column. The date is displayed in medium date format (e.g. Fri Aug 31).
|
// Builds the date column. The date is displayed in medium date format (e.g. Fri Aug 31).
|
||||||
Widget _buildMediumDatePicker(double offAxisFraction, TransitionBuilder itemPositioningBuilder, Widget selectionOverlay) {
|
Widget _buildMediumDatePicker(double offAxisFraction, TransitionBuilder itemPositioningBuilder, Widget? selectionOverlay) {
|
||||||
return NotificationListener<ScrollNotification>(
|
return NotificationListener<ScrollNotification>(
|
||||||
onNotification: (ScrollNotification notification) {
|
onNotification: (ScrollNotification notification) {
|
||||||
if (notification is ScrollStartNotification) {
|
if (notification is ScrollStartNotification) {
|
||||||
|
@ -794,7 +841,7 @@ class _CupertinoDatePickerDateTimeState extends State<CupertinoDatePicker> {
|
||||||
&& !(widget.maximumDate?.isBefore(rangeStart) ?? false);
|
&& !(widget.maximumDate?.isBefore(rangeStart) ?? false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildHourPicker(double offAxisFraction, TransitionBuilder itemPositioningBuilder, Widget selectionOverlay) {
|
Widget _buildHourPicker(double offAxisFraction, TransitionBuilder itemPositioningBuilder, Widget? selectionOverlay) {
|
||||||
return NotificationListener<ScrollNotification>(
|
return NotificationListener<ScrollNotification>(
|
||||||
onNotification: (ScrollNotification notification) {
|
onNotification: (ScrollNotification notification) {
|
||||||
if (notification is ScrollStartNotification) {
|
if (notification is ScrollStartNotification) {
|
||||||
|
@ -859,7 +906,7 @@ class _CupertinoDatePickerDateTimeState extends State<CupertinoDatePicker> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildMinutePicker(double offAxisFraction, TransitionBuilder itemPositioningBuilder, Widget selectionOverlay) {
|
Widget _buildMinutePicker(double offAxisFraction, TransitionBuilder itemPositioningBuilder, Widget? selectionOverlay) {
|
||||||
return NotificationListener<ScrollNotification>(
|
return NotificationListener<ScrollNotification>(
|
||||||
onNotification: (ScrollNotification notification) {
|
onNotification: (ScrollNotification notification) {
|
||||||
if (notification is ScrollStartNotification) {
|
if (notification is ScrollStartNotification) {
|
||||||
|
@ -909,7 +956,7 @@ class _CupertinoDatePickerDateTimeState extends State<CupertinoDatePicker> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildAmPmPicker(double offAxisFraction, TransitionBuilder itemPositioningBuilder, Widget selectionOverlay) {
|
Widget _buildAmPmPicker(double offAxisFraction, TransitionBuilder itemPositioningBuilder, Widget? selectionOverlay) {
|
||||||
return NotificationListener<ScrollNotification>(
|
return NotificationListener<ScrollNotification>(
|
||||||
onNotification: (ScrollNotification notification) {
|
onNotification: (ScrollNotification notification) {
|
||||||
if (notification is ScrollStartNotification) {
|
if (notification is ScrollStartNotification) {
|
||||||
|
@ -1053,10 +1100,21 @@ class _CupertinoDatePickerDateTimeState extends State<CupertinoDatePicker> {
|
||||||
for (final (int i, double width) in columnWidths.indexed) {
|
for (final (int i, double width) in columnWidths.indexed) {
|
||||||
final (bool firstColumn, bool lastColumn) = (i == 0, i == columnWidths.length - 1);
|
final (bool firstColumn, bool lastColumn) = (i == 0, i == columnWidths.length - 1);
|
||||||
double offAxisFraction = 0.0;
|
double offAxisFraction = 0.0;
|
||||||
Widget selectionOverlay = _centerSelectionOverlay;
|
Widget? selectionOverlay = _centerSelectionOverlay;
|
||||||
|
|
||||||
|
if (widget.selectionOverlayBuilder != null) {
|
||||||
|
selectionOverlay =
|
||||||
|
widget.selectionOverlayBuilder!(context, selectedIndex: i, columnCount: columnWidths.length);
|
||||||
|
} else {
|
||||||
|
if (firstColumn) {
|
||||||
|
selectionOverlay = _startSelectionOverlay;
|
||||||
|
} else if (lastColumn) {
|
||||||
|
selectionOverlay = _endSelectionOverlay;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (firstColumn) {
|
if (firstColumn) {
|
||||||
offAxisFraction = -_kMaximumOffAxisFraction * textDirectionFactor;
|
offAxisFraction = -_kMaximumOffAxisFraction * textDirectionFactor;
|
||||||
selectionOverlay = _startSelectionOverlay;
|
|
||||||
} else if (i >= 2 || columnWidths.length == 2) {
|
} else if (i >= 2 || columnWidths.length == 2) {
|
||||||
offAxisFraction = _kMaximumOffAxisFraction * textDirectionFactor;
|
offAxisFraction = _kMaximumOffAxisFraction * textDirectionFactor;
|
||||||
}
|
}
|
||||||
|
@ -1064,7 +1122,6 @@ class _CupertinoDatePickerDateTimeState extends State<CupertinoDatePicker> {
|
||||||
EdgeInsets padding = const EdgeInsets.only(right: _kDatePickerPadSize);
|
EdgeInsets padding = const EdgeInsets.only(right: _kDatePickerPadSize);
|
||||||
if (lastColumn) {
|
if (lastColumn) {
|
||||||
padding = padding.flipped;
|
padding = padding.flipped;
|
||||||
selectionOverlay = _endSelectionOverlay;
|
|
||||||
}
|
}
|
||||||
if (textDirectionFactor == -1) {
|
if (textDirectionFactor == -1) {
|
||||||
padding = padding.flipped;
|
padding = padding.flipped;
|
||||||
|
@ -1204,7 +1261,7 @@ class _CupertinoDatePickerDateState extends State<CupertinoDatePicker> {
|
||||||
// Let `DateTime` handle the year/month overflow.
|
// Let `DateTime` handle the year/month overflow.
|
||||||
DateTime _lastDayInMonth(int year, int month) => DateTime(year, month + 1, 0);
|
DateTime _lastDayInMonth(int year, int month) => DateTime(year, month + 1, 0);
|
||||||
|
|
||||||
Widget _buildDayPicker(double offAxisFraction, TransitionBuilder itemPositioningBuilder, Widget selectionOverlay) {
|
Widget _buildDayPicker(double offAxisFraction, TransitionBuilder itemPositioningBuilder, Widget? selectionOverlay) {
|
||||||
final int daysInCurrentMonth = _lastDayInMonth(selectedYear, selectedMonth).day;
|
final int daysInCurrentMonth = _lastDayInMonth(selectedYear, selectedMonth).day;
|
||||||
return NotificationListener<ScrollNotification>(
|
return NotificationListener<ScrollNotification>(
|
||||||
onNotification: (ScrollNotification notification) {
|
onNotification: (ScrollNotification notification) {
|
||||||
|
@ -1255,7 +1312,7 @@ class _CupertinoDatePickerDateState extends State<CupertinoDatePicker> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildMonthPicker(double offAxisFraction, TransitionBuilder itemPositioningBuilder, Widget selectionOverlay) {
|
Widget _buildMonthPicker(double offAxisFraction, TransitionBuilder itemPositioningBuilder, Widget? selectionOverlay) {
|
||||||
return NotificationListener<ScrollNotification>(
|
return NotificationListener<ScrollNotification>(
|
||||||
onNotification: (ScrollNotification notification) {
|
onNotification: (ScrollNotification notification) {
|
||||||
if (notification is ScrollStartNotification) {
|
if (notification is ScrollStartNotification) {
|
||||||
|
@ -1301,7 +1358,7 @@ class _CupertinoDatePickerDateState extends State<CupertinoDatePicker> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildYearPicker(double offAxisFraction, TransitionBuilder itemPositioningBuilder, Widget selectionOverlay) {
|
Widget _buildYearPicker(double offAxisFraction, TransitionBuilder itemPositioningBuilder, Widget? selectionOverlay) {
|
||||||
return NotificationListener<ScrollNotification>(
|
return NotificationListener<ScrollNotification>(
|
||||||
onNotification: (ScrollNotification notification) {
|
onNotification: (ScrollNotification notification) {
|
||||||
if (notification is ScrollStartNotification) {
|
if (notification is ScrollStartNotification) {
|
||||||
|
@ -1462,13 +1519,20 @@ class _CupertinoDatePickerDateState extends State<CupertinoDatePicker> {
|
||||||
padding = const EdgeInsets.only(left: _kDatePickerPadSize);
|
padding = const EdgeInsets.only(left: _kDatePickerPadSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget selectionOverlay = _centerSelectionOverlay;
|
Widget? selectionOverlay = _centerSelectionOverlay;
|
||||||
if (firstColumn) {
|
|
||||||
selectionOverlay = _startSelectionOverlay;
|
if (widget.selectionOverlayBuilder != null) {
|
||||||
} else if (i == columnWidths.length - 1) {
|
selectionOverlay =
|
||||||
selectionOverlay = _endSelectionOverlay;
|
widget.selectionOverlayBuilder!(context, selectedIndex: i, columnCount: columnWidths.length);
|
||||||
|
} else {
|
||||||
|
if (firstColumn) {
|
||||||
|
selectionOverlay = _startSelectionOverlay;
|
||||||
|
} else if (lastColumn) {
|
||||||
|
selectionOverlay = _endSelectionOverlay;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
totalColumnWidths += width + (2 * _kDatePickerPadSize);
|
totalColumnWidths += width + (2 * _kDatePickerPadSize);
|
||||||
|
|
||||||
pickers.add(LayoutId(
|
pickers.add(LayoutId(
|
||||||
|
@ -1593,7 +1657,7 @@ class _CupertinoDatePickerMonthYearState extends State<CupertinoDatePicker> {
|
||||||
estimatedColumnWidths[_PickerColumnType.year.index] = CupertinoDatePicker._getColumnWidth(_PickerColumnType.year, localizations, context, false);
|
estimatedColumnWidths[_PickerColumnType.year.index] = CupertinoDatePicker._getColumnWidth(_PickerColumnType.year, localizations, context, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildMonthPicker(double offAxisFraction, TransitionBuilder itemPositioningBuilder, Widget selectionOverlay) {
|
Widget _buildMonthPicker(double offAxisFraction, TransitionBuilder itemPositioningBuilder, Widget? selectionOverlay) {
|
||||||
return NotificationListener<ScrollNotification>(
|
return NotificationListener<ScrollNotification>(
|
||||||
onNotification: (ScrollNotification notification) {
|
onNotification: (ScrollNotification notification) {
|
||||||
if (notification is ScrollStartNotification) {
|
if (notification is ScrollStartNotification) {
|
||||||
|
@ -1639,7 +1703,7 @@ class _CupertinoDatePickerMonthYearState extends State<CupertinoDatePicker> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildYearPicker(double offAxisFraction, TransitionBuilder itemPositioningBuilder, Widget selectionOverlay) {
|
Widget _buildYearPicker(double offAxisFraction, TransitionBuilder itemPositioningBuilder, Widget? selectionOverlay) {
|
||||||
return NotificationListener<ScrollNotification>(
|
return NotificationListener<ScrollNotification>(
|
||||||
onNotification: (ScrollNotification notification) {
|
onNotification: (ScrollNotification notification) {
|
||||||
if (notification is ScrollStartNotification) {
|
if (notification is ScrollStartNotification) {
|
||||||
|
@ -1772,6 +1836,19 @@ class _CupertinoDatePickerMonthYearState extends State<CupertinoDatePicker> {
|
||||||
|
|
||||||
totalColumnWidths += width + (2 * _kDatePickerPadSize);
|
totalColumnWidths += width + (2 * _kDatePickerPadSize);
|
||||||
|
|
||||||
|
Widget? selectionOverlay = _centerSelectionOverlay;
|
||||||
|
|
||||||
|
if (widget.selectionOverlayBuilder != null) {
|
||||||
|
selectionOverlay =
|
||||||
|
widget.selectionOverlayBuilder!(context, selectedIndex: i, columnCount: columnWidths.length);
|
||||||
|
} else {
|
||||||
|
if (firstColumn) {
|
||||||
|
selectionOverlay = _startSelectionOverlay;
|
||||||
|
} else if (lastColumn) {
|
||||||
|
selectionOverlay = _endSelectionOverlay;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pickers.add(LayoutId(
|
pickers.add(LayoutId(
|
||||||
id: i,
|
id: i,
|
||||||
child: pickerBuilders[i](
|
child: pickerBuilders[i](
|
||||||
|
@ -1797,11 +1874,7 @@ class _CupertinoDatePickerMonthYearState extends State<CupertinoDatePicker> {
|
||||||
child: contents,
|
child: contents,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
switch (lastColumn) {
|
selectionOverlay,
|
||||||
_ when firstColumn => _startSelectionOverlay,
|
|
||||||
false => _centerSelectionOverlay,
|
|
||||||
true => _endSelectionOverlay,
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -1912,6 +1985,7 @@ class CupertinoTimerPicker extends StatefulWidget {
|
||||||
this.backgroundColor,
|
this.backgroundColor,
|
||||||
this.itemExtent = _kItemExtent,
|
this.itemExtent = _kItemExtent,
|
||||||
required this.onTimerDurationChanged,
|
required this.onTimerDurationChanged,
|
||||||
|
this.selectionOverlayBuilder,
|
||||||
}) : assert(initialTimerDuration >= Duration.zero),
|
}) : assert(initialTimerDuration >= Duration.zero),
|
||||||
assert(initialTimerDuration < const Duration(days: 1)),
|
assert(initialTimerDuration < const Duration(days: 1)),
|
||||||
assert(minuteInterval > 0 && 60 % minuteInterval == 0),
|
assert(minuteInterval > 0 && 60 % minuteInterval == 0),
|
||||||
|
@ -1955,6 +2029,46 @@ class CupertinoTimerPicker extends StatefulWidget {
|
||||||
/// Defaults to a value that matches the default iOS timer picker wheel.
|
/// Defaults to a value that matches the default iOS timer picker wheel.
|
||||||
final double itemExtent;
|
final double itemExtent;
|
||||||
|
|
||||||
|
/// A function that returns a widget that is overlaid on the picker
|
||||||
|
/// to highlight the currently selected entry.
|
||||||
|
///
|
||||||
|
/// If unspecified, it defaults to a [CupertinoPickerDefaultSelectionOverlay]
|
||||||
|
/// which is a gray rounded rectangle overlay in iOS 14 style.
|
||||||
|
///
|
||||||
|
/// If the selection overlay builder returns null, no overlay will be drawn.
|
||||||
|
///
|
||||||
|
/// {@tool snippet}
|
||||||
|
///
|
||||||
|
/// This example shows how to recreate the default selection overlay
|
||||||
|
/// with selectionOverlayBuilder.
|
||||||
|
///
|
||||||
|
/// ```dart
|
||||||
|
/// CupertinoTimerPicker(
|
||||||
|
/// onTimerDurationChanged: (Duration newDateTime) {},
|
||||||
|
/// selectionOverlayBuilder: (
|
||||||
|
/// BuildContext context, {
|
||||||
|
/// required int selectedIndex,
|
||||||
|
/// required int columnCount,
|
||||||
|
/// }) {
|
||||||
|
/// if (selectedIndex == 0) {
|
||||||
|
/// return const CupertinoPickerDefaultSelectionOverlay(
|
||||||
|
/// capEndEdge: false,
|
||||||
|
/// );
|
||||||
|
/// } else if (selectedIndex == columnCount - 1) {
|
||||||
|
/// return const CupertinoPickerDefaultSelectionOverlay(
|
||||||
|
/// capStartEdge: false,
|
||||||
|
/// );
|
||||||
|
/// }
|
||||||
|
/// return const CupertinoPickerDefaultSelectionOverlay(
|
||||||
|
/// capStartEdge: false,
|
||||||
|
/// capEndEdge: false,
|
||||||
|
/// );
|
||||||
|
/// },
|
||||||
|
/// )
|
||||||
|
/// ```
|
||||||
|
/// {@end-tool}
|
||||||
|
final SelectionOverlayBuilder? selectionOverlayBuilder;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<StatefulWidget> createState() => _CupertinoTimerPickerState();
|
State<StatefulWidget> createState() => _CupertinoTimerPickerState();
|
||||||
}
|
}
|
||||||
|
@ -2182,7 +2296,7 @@ class _CupertinoTimerPickerState extends State<CupertinoTimerPicker> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildHourPicker(EdgeInsetsDirectional additionalPadding, Widget selectionOverlay) {
|
Widget _buildHourPicker(EdgeInsetsDirectional additionalPadding, Widget? selectionOverlay) {
|
||||||
_hourScrollController ??= FixedExtentScrollController(
|
_hourScrollController ??= FixedExtentScrollController(
|
||||||
initialItem: selectedHour!
|
initialItem: selectedHour!
|
||||||
);
|
);
|
||||||
|
@ -2221,7 +2335,7 @@ class _CupertinoTimerPickerState extends State<CupertinoTimerPicker> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildHourColumn(EdgeInsetsDirectional additionalPadding, Widget selectionOverlay) {
|
Widget _buildHourColumn(EdgeInsetsDirectional additionalPadding, Widget? selectionOverlay) {
|
||||||
additionalPadding = EdgeInsetsDirectional.only(
|
additionalPadding = EdgeInsetsDirectional.only(
|
||||||
start: math.max(additionalPadding.start, 0),
|
start: math.max(additionalPadding.start, 0),
|
||||||
end: math.max(additionalPadding.end, 0),
|
end: math.max(additionalPadding.end, 0),
|
||||||
|
@ -2244,7 +2358,7 @@ class _CupertinoTimerPickerState extends State<CupertinoTimerPicker> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildMinutePicker(EdgeInsetsDirectional additionalPadding, Widget selectionOverlay) {
|
Widget _buildMinutePicker(EdgeInsetsDirectional additionalPadding, Widget? selectionOverlay) {
|
||||||
_minuteScrollController ??= FixedExtentScrollController(
|
_minuteScrollController ??= FixedExtentScrollController(
|
||||||
initialItem: selectedMinute ~/ widget.minuteInterval,
|
initialItem: selectedMinute ~/ widget.minuteInterval,
|
||||||
);
|
);
|
||||||
|
@ -2288,7 +2402,7 @@ class _CupertinoTimerPickerState extends State<CupertinoTimerPicker> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildMinuteColumn(EdgeInsetsDirectional additionalPadding, Widget selectionOverlay) {
|
Widget _buildMinuteColumn(EdgeInsetsDirectional additionalPadding, Widget? selectionOverlay) {
|
||||||
additionalPadding = EdgeInsetsDirectional.only(
|
additionalPadding = EdgeInsetsDirectional.only(
|
||||||
start: math.max(additionalPadding.start, 0),
|
start: math.max(additionalPadding.start, 0),
|
||||||
end: math.max(additionalPadding.end, 0),
|
end: math.max(additionalPadding.end, 0),
|
||||||
|
@ -2311,7 +2425,7 @@ class _CupertinoTimerPickerState extends State<CupertinoTimerPicker> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildSecondPicker(EdgeInsetsDirectional additionalPadding, Widget selectionOverlay) {
|
Widget _buildSecondPicker(EdgeInsetsDirectional additionalPadding, Widget? selectionOverlay) {
|
||||||
_secondScrollController ??= FixedExtentScrollController(
|
_secondScrollController ??= FixedExtentScrollController(
|
||||||
initialItem: selectedSecond! ~/ widget.secondInterval,
|
initialItem: selectedSecond! ~/ widget.secondInterval,
|
||||||
);
|
);
|
||||||
|
@ -2355,7 +2469,7 @@ class _CupertinoTimerPickerState extends State<CupertinoTimerPicker> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildSecondColumn(EdgeInsetsDirectional additionalPadding, Widget selectionOverlay) {
|
Widget _buildSecondColumn(EdgeInsetsDirectional additionalPadding, Widget? selectionOverlay) {
|
||||||
additionalPadding = EdgeInsetsDirectional.only(
|
additionalPadding = EdgeInsetsDirectional.only(
|
||||||
start: math.max(additionalPadding.start, 0),
|
start: math.max(additionalPadding.start, 0),
|
||||||
end: math.max(additionalPadding.end, 0),
|
end: math.max(additionalPadding.end, 0),
|
||||||
|
@ -2447,20 +2561,30 @@ class _CupertinoTimerPickerState extends State<CupertinoTimerPicker> {
|
||||||
minuteColumnEndPadding = _kTimerPickerMinHorizontalPadding;
|
minuteColumnEndPadding = _kTimerPickerMinHorizontalPadding;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget? hourSelectionOverlay = _startSelectionOverlay;
|
||||||
|
Widget? minuteSelectionOverlay = _endSelectionOverlay;
|
||||||
|
|
||||||
|
if (widget.selectionOverlayBuilder != null) {
|
||||||
|
hourSelectionOverlay =
|
||||||
|
widget.selectionOverlayBuilder!(context, selectedIndex: 0, columnCount: 2);
|
||||||
|
minuteSelectionOverlay =
|
||||||
|
widget.selectionOverlayBuilder!(context, selectedIndex: 1, columnCount: 2);
|
||||||
|
}
|
||||||
|
|
||||||
columns = <Widget>[
|
columns = <Widget>[
|
||||||
_buildHourColumn(
|
_buildHourColumn(
|
||||||
EdgeInsetsDirectional.only(
|
EdgeInsetsDirectional.only(
|
||||||
start: hourColumnStartPadding,
|
start: hourColumnStartPadding,
|
||||||
end: pickerColumnWidth - hourColumnStartPadding - hourLabelContentWidth,
|
end: pickerColumnWidth - hourColumnStartPadding - hourLabelContentWidth,
|
||||||
),
|
),
|
||||||
_startSelectionOverlay,
|
hourSelectionOverlay,
|
||||||
),
|
),
|
||||||
_buildMinuteColumn(
|
_buildMinuteColumn(
|
||||||
EdgeInsetsDirectional.only(
|
EdgeInsetsDirectional.only(
|
||||||
start: pickerColumnWidth - minuteColumnEndPadding - minuteLabelContentWidth,
|
start: pickerColumnWidth - minuteColumnEndPadding - minuteLabelContentWidth,
|
||||||
end: minuteColumnEndPadding,
|
end: minuteColumnEndPadding,
|
||||||
),
|
),
|
||||||
_endSelectionOverlay,
|
minuteSelectionOverlay,
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
case CupertinoTimerPickerMode.ms:
|
case CupertinoTimerPickerMode.ms:
|
||||||
|
@ -2477,20 +2601,30 @@ class _CupertinoTimerPickerState extends State<CupertinoTimerPicker> {
|
||||||
minuteColumnStartPadding = _kTimerPickerMinHorizontalPadding;
|
minuteColumnStartPadding = _kTimerPickerMinHorizontalPadding;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget? minuteSelectionOverlay = _startSelectionOverlay;
|
||||||
|
Widget? secondSelectionOverlay = _endSelectionOverlay;
|
||||||
|
|
||||||
|
if (widget.selectionOverlayBuilder != null) {
|
||||||
|
minuteSelectionOverlay =
|
||||||
|
widget.selectionOverlayBuilder!(context, selectedIndex: 0, columnCount: 2);
|
||||||
|
secondSelectionOverlay =
|
||||||
|
widget.selectionOverlayBuilder!(context, selectedIndex: 1, columnCount: 2);
|
||||||
|
}
|
||||||
|
|
||||||
columns = <Widget>[
|
columns = <Widget>[
|
||||||
_buildMinuteColumn(
|
_buildMinuteColumn(
|
||||||
EdgeInsetsDirectional.only(
|
EdgeInsetsDirectional.only(
|
||||||
start: minuteColumnStartPadding,
|
start: minuteColumnStartPadding,
|
||||||
end: pickerColumnWidth - minuteColumnStartPadding - minuteLabelContentWidth,
|
end: pickerColumnWidth - minuteColumnStartPadding - minuteLabelContentWidth,
|
||||||
),
|
),
|
||||||
_startSelectionOverlay,
|
minuteSelectionOverlay,
|
||||||
),
|
),
|
||||||
_buildSecondColumn(
|
_buildSecondColumn(
|
||||||
EdgeInsetsDirectional.only(
|
EdgeInsetsDirectional.only(
|
||||||
start: pickerColumnWidth - secondColumnEndPadding - minuteLabelContentWidth,
|
start: pickerColumnWidth - secondColumnEndPadding - minuteLabelContentWidth,
|
||||||
end: secondColumnEndPadding,
|
end: secondColumnEndPadding,
|
||||||
),
|
),
|
||||||
_endSelectionOverlay,
|
secondSelectionOverlay,
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
case CupertinoTimerPickerMode.hms:
|
case CupertinoTimerPickerMode.hms:
|
||||||
|
@ -2501,27 +2635,41 @@ class _CupertinoTimerPickerState extends State<CupertinoTimerPicker> {
|
||||||
final double secondColumnStartPadding =
|
final double secondColumnStartPadding =
|
||||||
pickerColumnWidth - baseLabelContentWidth - secondLabelWidth - _kTimerPickerMinHorizontalPadding;
|
pickerColumnWidth - baseLabelContentWidth - secondLabelWidth - _kTimerPickerMinHorizontalPadding;
|
||||||
|
|
||||||
|
|
||||||
|
Widget? hourSelectionOverlay = _startSelectionOverlay;
|
||||||
|
Widget? minuteSelectionOverlay = _centerSelectionOverlay;
|
||||||
|
Widget? secondSelectionOverlay = _endSelectionOverlay;
|
||||||
|
|
||||||
|
if (widget.selectionOverlayBuilder != null) {
|
||||||
|
hourSelectionOverlay =
|
||||||
|
widget.selectionOverlayBuilder!(context, selectedIndex: 0, columnCount: 3);
|
||||||
|
minuteSelectionOverlay =
|
||||||
|
widget.selectionOverlayBuilder!(context, selectedIndex: 1, columnCount: 3);
|
||||||
|
secondSelectionOverlay =
|
||||||
|
widget.selectionOverlayBuilder!(context, selectedIndex: 2, columnCount: 3);
|
||||||
|
}
|
||||||
|
|
||||||
columns = <Widget>[
|
columns = <Widget>[
|
||||||
_buildHourColumn(
|
_buildHourColumn(
|
||||||
EdgeInsetsDirectional.only(
|
EdgeInsetsDirectional.only(
|
||||||
start: _kTimerPickerMinHorizontalPadding,
|
start: _kTimerPickerMinHorizontalPadding,
|
||||||
end: math.max(hourColumnEndPadding, 0),
|
end: math.max(hourColumnEndPadding, 0),
|
||||||
),
|
),
|
||||||
_startSelectionOverlay,
|
hourSelectionOverlay,
|
||||||
),
|
),
|
||||||
_buildMinuteColumn(
|
_buildMinuteColumn(
|
||||||
EdgeInsetsDirectional.only(
|
EdgeInsetsDirectional.only(
|
||||||
start: minuteColumnPadding,
|
start: minuteColumnPadding,
|
||||||
end: minuteColumnPadding,
|
end: minuteColumnPadding,
|
||||||
),
|
),
|
||||||
_centerSelectionOverlay,
|
minuteSelectionOverlay,
|
||||||
),
|
),
|
||||||
_buildSecondColumn(
|
_buildSecondColumn(
|
||||||
EdgeInsetsDirectional.only(
|
EdgeInsetsDirectional.only(
|
||||||
start: math.max(secondColumnStartPadding, 0),
|
start: math.max(secondColumnStartPadding, 0),
|
||||||
end: _kTimerPickerMinHorizontalPadding,
|
end: _kTimerPickerMinHorizontalPadding,
|
||||||
),
|
),
|
||||||
_endSelectionOverlay,
|
secondSelectionOverlay,
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -2114,6 +2114,306 @@ void main() {
|
||||||
expect(find.textContaining('15').last, findsOneWidget);
|
expect(find.textContaining('15').last, findsOneWidget);
|
||||||
expect(find.text('2018'), findsOneWidget);
|
expect(find.text('2018'), findsOneWidget);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets('CupertinoDatePicker selectionOverlayBuilder with monthYear mode',
|
||||||
|
(WidgetTester tester) async {
|
||||||
|
|
||||||
|
final Widget selectionOverlay = Container(
|
||||||
|
color: const Color(0x12345678),
|
||||||
|
);
|
||||||
|
|
||||||
|
// For mode = CupertinoDatePickerMode.monthYear
|
||||||
|
await tester.pumpWidget(
|
||||||
|
CupertinoApp(
|
||||||
|
home: Center(
|
||||||
|
child: CupertinoDatePicker(
|
||||||
|
mode: CupertinoDatePickerMode.monthYear,
|
||||||
|
onDateTimeChanged: (DateTime date) {},
|
||||||
|
initialDateTime: DateTime(2018, 9, 15),
|
||||||
|
selectionOverlayBuilder: (
|
||||||
|
BuildContext context, {
|
||||||
|
required int selectedIndex,
|
||||||
|
required int columnCount,
|
||||||
|
}) {
|
||||||
|
return selectionOverlay;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Find the selection overlay.
|
||||||
|
expect(find.byWidget(selectionOverlay), findsExactly(2));
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('CupertinoDatePicker selectionOverlayBuilder with date mode',
|
||||||
|
(WidgetTester tester) async {
|
||||||
|
|
||||||
|
final Widget selectionOverlay = Container(
|
||||||
|
color: const Color(0x12345678),
|
||||||
|
);
|
||||||
|
|
||||||
|
// For mode = CupertinoDatePickerMode.date
|
||||||
|
await tester.pumpWidget(
|
||||||
|
CupertinoApp(
|
||||||
|
home: Center(
|
||||||
|
child: CupertinoDatePicker(
|
||||||
|
mode: CupertinoDatePickerMode.date,
|
||||||
|
onDateTimeChanged: (DateTime date) {},
|
||||||
|
initialDateTime: DateTime(2018, 9, 15),
|
||||||
|
selectionOverlayBuilder: (
|
||||||
|
BuildContext context, {
|
||||||
|
required int selectedIndex,
|
||||||
|
required int columnCount,
|
||||||
|
}) {
|
||||||
|
return selectionOverlay;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Find the selection overlay.
|
||||||
|
expect(find.byWidget(selectionOverlay), findsExactly(3));
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
testWidgets('CupertinoDatePicker selectionOverlayBuilder with time mode',
|
||||||
|
(WidgetTester tester) async {
|
||||||
|
|
||||||
|
final Widget selectionOverlay = Container(
|
||||||
|
color: const Color(0x12345678),
|
||||||
|
);
|
||||||
|
|
||||||
|
// For mode = CupertinoDatePickerMode.time
|
||||||
|
await tester.pumpWidget(
|
||||||
|
CupertinoApp(
|
||||||
|
home: Center(
|
||||||
|
child: CupertinoDatePicker(
|
||||||
|
mode: CupertinoDatePickerMode.time,
|
||||||
|
onDateTimeChanged: (DateTime date) {},
|
||||||
|
initialDateTime: DateTime(2018, 9, 15),
|
||||||
|
selectionOverlayBuilder: (
|
||||||
|
BuildContext context, {
|
||||||
|
required int selectedIndex,
|
||||||
|
required int columnCount,
|
||||||
|
}) {
|
||||||
|
return selectionOverlay;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Find the selection overlay.
|
||||||
|
expect(find.byWidget(selectionOverlay), findsExactly(3));
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('CupertinoDatePicker selectionOverlayBuilder with dateAndTime mode',
|
||||||
|
(WidgetTester tester) async {
|
||||||
|
|
||||||
|
final Widget selectionOverlay = Container(
|
||||||
|
color: const Color(0x12345678),
|
||||||
|
);
|
||||||
|
|
||||||
|
// For mode = CupertinoDatePickerMode.dateAndTime
|
||||||
|
await tester.pumpWidget(
|
||||||
|
CupertinoApp(
|
||||||
|
home: Center(
|
||||||
|
child: CupertinoDatePicker(
|
||||||
|
onDateTimeChanged: (DateTime date) {},
|
||||||
|
initialDateTime: DateTime(2018, 9, 15),
|
||||||
|
selectionOverlayBuilder: (
|
||||||
|
BuildContext context, {
|
||||||
|
required int selectedIndex,
|
||||||
|
required int columnCount,
|
||||||
|
}) {
|
||||||
|
return selectionOverlay;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Find the selection overlay.
|
||||||
|
expect(find.byWidget(selectionOverlay), findsExactly(4));
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('CupertinoTimerPicker selectionOverlayBuilder with hms mode',
|
||||||
|
(WidgetTester tester) async {
|
||||||
|
|
||||||
|
final Widget selectionOverlay = Container(
|
||||||
|
color: const Color(0x12345678),
|
||||||
|
);
|
||||||
|
|
||||||
|
// For mode = CupertinoTimerPickerMode.hms
|
||||||
|
await tester.pumpWidget(
|
||||||
|
CupertinoApp(
|
||||||
|
home: Center(
|
||||||
|
child: CupertinoTimerPicker(
|
||||||
|
onTimerDurationChanged: (Duration duration) {},
|
||||||
|
initialTimerDuration: const Duration(hours: 1, minutes: 1, seconds: 1),
|
||||||
|
selectionOverlayBuilder: (
|
||||||
|
BuildContext context, {
|
||||||
|
required int selectedIndex,
|
||||||
|
required int columnCount,
|
||||||
|
}) {
|
||||||
|
return selectionOverlay;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Find the selection overlay.
|
||||||
|
expect(find.byWidget(selectionOverlay), findsExactly(3));
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('CupertinoTimerPicker selectionOverlayBuilder with ms mode',
|
||||||
|
(WidgetTester tester) async {
|
||||||
|
|
||||||
|
final Widget selectionOverlay = Container(
|
||||||
|
color: const Color(0x12345678),
|
||||||
|
);
|
||||||
|
|
||||||
|
// For mode = CupertinoTimerPickerMode.ms
|
||||||
|
await tester.pumpWidget(
|
||||||
|
CupertinoApp(
|
||||||
|
home: Center(
|
||||||
|
child: CupertinoTimerPicker(
|
||||||
|
onTimerDurationChanged: (Duration duration) {},
|
||||||
|
mode: CupertinoTimerPickerMode.ms,
|
||||||
|
initialTimerDuration: const Duration(hours: 1, minutes: 1, seconds: 1),
|
||||||
|
selectionOverlayBuilder: (
|
||||||
|
BuildContext context, {
|
||||||
|
required int selectedIndex,
|
||||||
|
required int columnCount,
|
||||||
|
}) {
|
||||||
|
return selectionOverlay;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Find the selection overlay.
|
||||||
|
expect(find.byWidget(selectionOverlay), findsExactly(2));
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('CupertinoTimerPicker selectionOverlayBuilder with hm mode',
|
||||||
|
(WidgetTester tester) async {
|
||||||
|
|
||||||
|
final Widget selectionOverlay = Container(
|
||||||
|
color: const Color(0x12345678),
|
||||||
|
);
|
||||||
|
|
||||||
|
// For mode = CupertinoTimerPickerMode.hm
|
||||||
|
await tester.pumpWidget(
|
||||||
|
CupertinoApp(
|
||||||
|
home: Center(
|
||||||
|
child: CupertinoTimerPicker(
|
||||||
|
onTimerDurationChanged: (Duration duration) {},
|
||||||
|
mode: CupertinoTimerPickerMode.hm,
|
||||||
|
initialTimerDuration: const Duration(hours: 1, minutes: 1, seconds: 1),
|
||||||
|
selectionOverlayBuilder: (
|
||||||
|
BuildContext context, {
|
||||||
|
required int selectedIndex,
|
||||||
|
required int columnCount,
|
||||||
|
}) {
|
||||||
|
return selectionOverlay;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Find the selection overlay.
|
||||||
|
expect(find.byWidget(selectionOverlay), findsExactly(2));
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('CupertinoDatePicker selectionOverlayBuilder returns null',
|
||||||
|
(WidgetTester tester) async {
|
||||||
|
|
||||||
|
await tester.pumpWidget(
|
||||||
|
CupertinoApp(
|
||||||
|
home: Center(
|
||||||
|
child: CupertinoDatePicker(
|
||||||
|
onDateTimeChanged: (DateTime date) {},
|
||||||
|
initialDateTime: DateTime(2018, 9, 15),
|
||||||
|
selectionOverlayBuilder: (
|
||||||
|
BuildContext context, {
|
||||||
|
required int selectedIndex,
|
||||||
|
required int columnCount,
|
||||||
|
}) {
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(find.byType(CupertinoPicker), isNot(paints..rrect()));
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('CupertinoTimerPicker selectionOverlayBuilder returns null',
|
||||||
|
(WidgetTester tester) async {
|
||||||
|
|
||||||
|
await tester.pumpWidget(
|
||||||
|
CupertinoApp(
|
||||||
|
home: Center(
|
||||||
|
child: CupertinoTimerPicker(
|
||||||
|
onTimerDurationChanged: (Duration duration) {},
|
||||||
|
mode: CupertinoTimerPickerMode.hm,
|
||||||
|
initialTimerDuration: const Duration(hours: 1, minutes: 1, seconds: 1),
|
||||||
|
selectionOverlayBuilder: (
|
||||||
|
BuildContext context, {
|
||||||
|
required int selectedIndex,
|
||||||
|
required int columnCount,
|
||||||
|
}) {
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(find.byType(CupertinoPicker), isNot(paints..rrect()));
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('CupertinoTimerPicker selectionOverlayBuilder is explicitly passed null',
|
||||||
|
(WidgetTester tester) async {
|
||||||
|
|
||||||
|
await tester.pumpWidget(
|
||||||
|
CupertinoApp(
|
||||||
|
home: Center(
|
||||||
|
child: CupertinoTimerPicker(
|
||||||
|
onTimerDurationChanged: (Duration duration) {},
|
||||||
|
mode: CupertinoTimerPickerMode.hm,
|
||||||
|
initialTimerDuration: const Duration(hours: 1, minutes: 1, seconds: 1),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(find.byType(CupertinoPickerDefaultSelectionOverlay), findsExactly(2));
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('CupertinoDatePicker selectionOverlayBuilder is explicitly passed null',
|
||||||
|
(WidgetTester tester) async {
|
||||||
|
|
||||||
|
await tester.pumpWidget(
|
||||||
|
CupertinoApp(
|
||||||
|
home: Center(
|
||||||
|
child: CupertinoDatePicker(
|
||||||
|
onDateTimeChanged: (DateTime date) {},
|
||||||
|
initialDateTime: DateTime(2018, 9, 15),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(find.byType(CupertinoPickerDefaultSelectionOverlay), findsExactly(4));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildPicker({
|
Widget _buildPicker({
|
||||||
|
|
Loading…
Reference in a new issue