CupertinoPicker fidelity revision (#31464)
diff --git a/bin/internal/goldens.version b/bin/internal/goldens.version
index e167261..97e50e5 100644
--- a/bin/internal/goldens.version
+++ b/bin/internal/goldens.version
@@ -1 +1 @@
-09ebc5361187e9cc20ddc350dc047f95812c61a4
+8057c8e1e0276a2ae7c26a0e04d54f339f3c51ca
diff --git a/examples/flutter_gallery/lib/demo/cupertino/cupertino_picker_demo.dart b/examples/flutter_gallery/lib/demo/cupertino/cupertino_picker_demo.dart
index 0fcaa32..3bcc00f 100644
--- a/examples/flutter_gallery/lib/demo/cupertino/cupertino_picker_demo.dart
+++ b/examples/flutter_gallery/lib/demo/cupertino/cupertino_picker_demo.dart
@@ -95,8 +95,8 @@
setState(() => _selectedColorIndex = index);
},
children: List<Widget>.generate(coolColorNames.length, (int index) {
- return Center(child:
- Text(coolColorNames[index]),
+ return Center(
+ child: Text(coolColorNames[index]),
);
}),
),
diff --git a/packages/flutter/lib/src/cupertino/date_picker.dart b/packages/flutter/lib/src/cupertino/date_picker.dart
index 0bd31f4..1d19aec 100644
--- a/packages/flutter/lib/src/cupertino/date_picker.dart
+++ b/packages/flutter/lib/src/cupertino/date_picker.dart
@@ -8,13 +8,17 @@
import 'colors.dart';
import 'localizations.dart';
import 'picker.dart';
+import 'theme.dart';
// Default aesthetic values obtained by comparing with iOS pickers.
const double _kItemExtent = 32.0;
const double _kPickerWidth = 330.0;
const bool _kUseMagnifier = true;
-const double _kMagnification = 1.05;
+const double _kMagnification = 1.08;
const double _kDatePickerPadSize = 12.0;
+// The density of a date picker is different from a generic picker.
+// Eyeballed from iOS.
+const double _kSqueeze = 1.25;
// Considers setting the default background color from the theme, in the future.
const Color _kBackgroundColor = CupertinoColors.white;
@@ -22,6 +26,10 @@
letterSpacing: -0.83,
);
+TextStyle _themeTextStyle(BuildContext context) {
+ return CupertinoTheme.of(context).textTheme.dateTimePickerTextStyle;
+}
+
// 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.
@@ -58,6 +66,13 @@
if (index == 0 || index == columnWidths.length - 1)
childWidth += remainingWidth / 2;
+ assert(
+ childWidth >= 0,
+ 'Insufficient horizontal space to render the CupertinoDatePicker '
+ 'because the parent is too narrow at ${size.width}px.\n'
+ 'An additional ${-remainingWidth}px is needed to avoid overlapping '
+ 'columns.',
+ );
layoutChild(index, BoxConstraints.tight(Size(childWidth, size.height)));
positionChild(index, Offset(currentHorizontalOffset, 0.0));
@@ -131,6 +146,13 @@
/// * US-English: [July | 13 | 2012]
/// * Vietnamese: [13 | Tháng 7 | 2012]
///
+/// Can be used with [showCupertinoModalPopup] to display the picker modally at
+/// the bottom of the screen.
+///
+/// Sizes itself to its parent and may not render correctly if not given the
+/// full screen width. Content texts are shown with
+/// [CupertinoTextThemeData.dateTimePickerTextStyle].
+///
/// See also:
///
/// * [CupertinoTimerPicker], the class that implements the iOS-style timer picker.
@@ -321,7 +343,7 @@
final TextPainter painter = TextPainter(
text: TextSpan(
- style: DefaultTextStyle.of(context).style,
+ style: _themeTextStyle(context),
text: longestText,
),
textDirection: Directionality.of(context),
@@ -339,6 +361,10 @@
typedef _ColumnBuilder = Widget Function(double offAxisFraction, TransitionBuilder itemPositioningBuilder);
class _CupertinoDatePickerDateTimeState extends State<CupertinoDatePicker> {
+ // Fraction of the farthest column's vanishing point vs its width. Eyeballed
+ // vs iOS.
+ static const double _kMaximumOffAxisFraction = 0.45;
+
int textDirectionFactor;
CupertinoLocalizations localizations;
@@ -462,6 +488,7 @@
useMagnifier: _kUseMagnifier,
magnification: _kMagnification,
backgroundColor: _kBackgroundColor,
+ squeeze: _kSqueeze,
onSelectedItemChanged: (int index) {
selectedDayFromInitial = index;
widget.onDateTimeChanged(_getDateTime());
@@ -478,9 +505,21 @@
if (widget.maximumDate != null && dateTime.isAfter(widget.maximumDate))
return null;
+ final DateTime now = DateTime.now();
+ String dateText;
+
+ if (dateTime == DateTime(now.year, now.month, now.day)) {
+ dateText = localizations.todayLabel;
+ } else {
+ dateText = localizations.datePickerMediumDate(dateTime);
+ }
+
return itemPositioningBuilder(
context,
- Text(localizations.datePickerMediumDate(dateTime)),
+ Text(
+ dateText,
+ style: _themeTextStyle(context),
+ ),
);
},
);
@@ -494,6 +533,7 @@
useMagnifier: _kUseMagnifier,
magnification: _kMagnification,
backgroundColor: _kBackgroundColor,
+ squeeze: _kSqueeze,
onSelectedItemChanged: (int index) {
if (widget.use24hFormat) {
selectedHour = index;
@@ -531,6 +571,7 @@
Text(
localizations.datePickerHour(hour),
semanticsLabel: localizations.datePickerHourSemanticsLabel(hour),
+ style: _themeTextStyle(context),
),
);
}),
@@ -546,6 +587,7 @@
useMagnifier: _kUseMagnifier,
magnification: _kMagnification,
backgroundColor: _kBackgroundColor,
+ squeeze: _kSqueeze,
onSelectedItemChanged: (int index) {
selectedMinute = index * widget.minuteInterval;
widget.onDateTimeChanged(_getDateTime());
@@ -557,6 +599,7 @@
Text(
localizations.datePickerMinute(minute),
semanticsLabel: localizations.datePickerMinuteSemanticsLabel(minute),
+ style: _themeTextStyle(context),
),
);
}),
@@ -572,6 +615,7 @@
useMagnifier: _kUseMagnifier,
magnification: _kMagnification,
backgroundColor: _kBackgroundColor,
+ squeeze: _kSqueeze,
onSelectedItemChanged: (int index) {
selectedAmPm = index;
widget.onDateTimeChanged(_getDateTime());
@@ -582,7 +626,8 @@
Text(
index == 0
? localizations.anteMeridiemAbbreviation
- : localizations.postMeridiemAbbreviation
+ : localizations.postMeridiemAbbreviation,
+ style: _themeTextStyle(context),
),
);
}),
@@ -630,9 +675,9 @@
for (int i = 0; i < columnWidths.length; i++) {
double offAxisFraction = 0.0;
if (i == 0)
- offAxisFraction = -0.5 * textDirectionFactor;
+ offAxisFraction = -_kMaximumOffAxisFraction * textDirectionFactor;
else if (i >= 2 || columnWidths.length == 2)
- offAxisFraction = 0.5 * textDirectionFactor;
+ offAxisFraction = _kMaximumOffAxisFraction * textDirectionFactor;
EdgeInsets padding = const EdgeInsets.only(right: _kDatePickerPadSize);
if (i == columnWidths.length - 1)
@@ -735,21 +780,22 @@
useMagnifier: _kUseMagnifier,
magnification: _kMagnification,
backgroundColor: _kBackgroundColor,
+ squeeze: _kSqueeze,
onSelectedItemChanged: (int index) {
selectedDay = index + 1;
if (DateTime(selectedYear, selectedMonth, selectedDay).day == selectedDay)
widget.onDateTimeChanged(DateTime(selectedYear, selectedMonth, selectedDay));
},
children: List<Widget>.generate(31, (int index) {
- TextStyle disableTextStyle; // Null if not out of range.
+ TextStyle textStyle = _themeTextStyle(context);
if (index >= daysInCurrentMonth) {
- disableTextStyle = const TextStyle(color: CupertinoColors.inactiveGray);
+ textStyle = textStyle.copyWith(color: CupertinoColors.inactiveGray);
}
return itemPositioningBuilder(
context,
Text(
localizations.datePickerDayOfMonth(index + 1),
- style: disableTextStyle,
+ style: textStyle,
),
);
}),
@@ -765,6 +811,7 @@
useMagnifier: _kUseMagnifier,
magnification: _kMagnification,
backgroundColor: _kBackgroundColor,
+ squeeze: _kSqueeze,
onSelectedItemChanged: (int index) {
selectedMonth = index + 1;
if (DateTime(selectedYear, selectedMonth, selectedDay).day == selectedDay)
@@ -773,7 +820,10 @@
children: List<Widget>.generate(12, (int index) {
return itemPositioningBuilder(
context,
- Text(localizations.datePickerMonth(index + 1)),
+ Text(
+ localizations.datePickerMonth(index + 1),
+ style: _themeTextStyle(context),
+ ),
);
}),
looping: true,
@@ -802,7 +852,10 @@
return itemPositioningBuilder(
context,
- Text(localizations.datePickerYear(index)),
+ Text(
+ localizations.datePickerYear(index),
+ style: _themeTextStyle(context),
+ ),
);
},
);
@@ -956,6 +1009,8 @@
///
/// There are several modes of the timer picker listed in [CupertinoTimerPickerMode].
///
+/// Sizes itself to its parent.
+///
/// See also:
///
/// * [CupertinoDatePicker], the class that implements different display modes
@@ -1045,7 +1100,7 @@
Widget _buildLabel(String text) {
return Text(
text,
- textScaleFactor: 0.8,
+ textScaleFactor: 0.9,
style: const TextStyle(fontWeight: FontWeight.w600),
);
}
@@ -1067,6 +1122,7 @@
offAxisFraction: -0.5 * textDirectionFactor,
itemExtent: _kItemExtent,
backgroundColor: _kBackgroundColor,
+ squeeze: _kSqueeze,
onSelectedItemChanged: (int index) {
setState(() {
selectedHour = index;
@@ -1145,6 +1201,7 @@
offAxisFraction: offAxisFraction,
itemExtent: _kItemExtent,
backgroundColor: _kBackgroundColor,
+ squeeze: _kSqueeze,
onSelectedItemChanged: (int index) {
setState(() {
selectedMinute = index * widget.minuteInterval;
@@ -1257,6 +1314,7 @@
offAxisFraction: offAxisFraction,
itemExtent: _kItemExtent,
backgroundColor: _kBackgroundColor,
+ squeeze: _kSqueeze,
onSelectedItemChanged: (int index) {
setState(() {
selectedSecond = index * widget.secondInterval;
diff --git a/packages/flutter/lib/src/cupertino/localizations.dart b/packages/flutter/lib/src/cupertino/localizations.dart
index 42e412e..075fc0b 100644
--- a/packages/flutter/lib/src/cupertino/localizations.dart
+++ b/packages/flutter/lib/src/cupertino/localizations.dart
@@ -142,6 +142,10 @@
// The global version uses the translated string from the arb file.
String get postMeridiemAbbreviation;
+ /// Label shown in date pickers when the date is today.
+ // The global version uses the translated string from the arb file.
+ String get todayLabel;
+
/// The term used by the system to announce dialog alerts.
// The global version uses the translated string from the arb file.
String get alertDialogLabel;
@@ -339,6 +343,9 @@
String get postMeridiemAbbreviation => 'PM';
@override
+ String get todayLabel => 'Today';
+
+ @override
String get alertDialogLabel => 'Alert';
@override
@@ -354,10 +361,10 @@
String timerPickerHourLabel(int hour) => hour == 1 ? 'hour' : 'hours';
@override
- String timerPickerMinuteLabel(int minute) => 'min';
+ String timerPickerMinuteLabel(int minute) => 'min.';
@override
- String timerPickerSecondLabel(int second) => 'sec';
+ String timerPickerSecondLabel(int second) => 'sec.';
@override
String get cutButtonLabel => 'Cut';
diff --git a/packages/flutter/lib/src/cupertino/picker.dart b/packages/flutter/lib/src/cupertino/picker.dart
index bd3e855..63a7efb 100644
--- a/packages/flutter/lib/src/cupertino/picker.dart
+++ b/packages/flutter/lib/src/cupertino/picker.dart
@@ -7,13 +7,16 @@
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
+import 'theme.dart';
+
/// Color of the 'magnifier' lens border.
const Color _kHighlighterBorder = Color(0xFF7F7F7F);
const Color _kDefaultBackground = Color(0xFFD2D4DB);
-// Eyeballed values comparing with a native picker.
-// Values closer to PI produces denser flatter lists.
-const double _kDefaultDiameterRatio = 1.35;
-const double _kDefaultPerspective = 0.004;
+// Eyeballed values comparing with a native picker to produce the right
+// curvatures and densities.
+const double _kDefaultDiameterRatio = 1.07;
+const double _kDefaultPerspective = 0.003;
+const double _kSqueeze = 1.45;
/// Opacity fraction value that hides the wheel above and below the 'magnifier'
/// lens with the same color as the background.
const double _kForegroundScreenOpacityFraction = 0.7;
@@ -26,6 +29,11 @@
/// Can be used with [showCupertinoModalPopup] to display the picker modally at the
/// bottom of the screen.
///
+/// Sizes itself to its parent. All children are sized to the same size based
+/// on [itemExtent].
+///
+/// By default, descendent texts are shown with [CupertinoTextThemeData.pickerTextStyle].
+///
/// See also:
///
/// * [ListWheelScrollView], the generic widget backing this picker without
@@ -58,6 +66,7 @@
this.useMagnifier = false,
this.magnification = 1.0,
this.scrollController,
+ this.squeeze = _kSqueeze,
@required this.itemExtent,
@required this.onSelectedItemChanged,
@required List<Widget> children,
@@ -68,6 +77,8 @@
assert(magnification > 0),
assert(itemExtent != null),
assert(itemExtent > 0),
+ assert(squeeze != null),
+ assert(squeeze > 0),
childDelegate = looping
? ListWheelChildLoopingListDelegate(children: children)
: ListWheelChildListDelegate(children: children),
@@ -98,6 +109,7 @@
this.useMagnifier = false,
this.magnification = 1.0,
this.scrollController,
+ this.squeeze = _kSqueeze,
@required this.itemExtent,
@required this.onSelectedItemChanged,
@required IndexedWidgetBuilder itemBuilder,
@@ -108,6 +120,8 @@
assert(magnification > 0),
assert(itemExtent != null),
assert(itemExtent > 0),
+ assert(squeeze != null),
+ assert(squeeze > 0),
childDelegate = ListWheelChildBuilderDelegate(builder: itemBuilder, childCount: childCount),
super(key: key);
@@ -151,6 +165,11 @@
/// height. Must not be null and must be positive.
final double itemExtent;
+ /// {@macro flutter.rendering.wheelList.squeeze}
+ ///
+ /// Defaults to `1.45` fo visually mimic iOS.
+ final double squeeze;
+
/// An option callback when the currently centered item changes.
///
/// Value changes when the item closest to the center changes.
@@ -313,28 +332,32 @@
@override
Widget build(BuildContext context) {
- Widget result = Stack(
- children: <Widget>[
- Positioned.fill(
- child: _CupertinoPickerSemantics(
- scrollController: widget.scrollController ?? _controller,
- child: ListWheelScrollView.useDelegate(
- controller: widget.scrollController ?? _controller,
- physics: const FixedExtentScrollPhysics(),
- diameterRatio: widget.diameterRatio,
- perspective: _kDefaultPerspective,
- offAxisFraction: widget.offAxisFraction,
- useMagnifier: widget.useMagnifier,
- magnification: widget.magnification,
- itemExtent: widget.itemExtent,
- onSelectedItemChanged: _handleSelectedItemChanged,
- childDelegate: widget.childDelegate,
+ Widget result = DefaultTextStyle(
+ style: CupertinoTheme.of(context).textTheme.pickerTextStyle,
+ child: Stack(
+ children: <Widget>[
+ Positioned.fill(
+ child: _CupertinoPickerSemantics(
+ scrollController: widget.scrollController ?? _controller,
+ child: ListWheelScrollView.useDelegate(
+ controller: widget.scrollController ?? _controller,
+ physics: const FixedExtentScrollPhysics(),
+ diameterRatio: widget.diameterRatio,
+ perspective: _kDefaultPerspective,
+ offAxisFraction: widget.offAxisFraction,
+ useMagnifier: widget.useMagnifier,
+ magnification: widget.magnification,
+ itemExtent: widget.itemExtent,
+ squeeze: widget.squeeze,
+ onSelectedItemChanged: _handleSelectedItemChanged,
+ childDelegate: widget.childDelegate,
+ ),
),
),
- ),
- _buildGradientScreen(),
- _buildMagnifierScreen(),
- ],
+ _buildGradientScreen(),
+ _buildMagnifierScreen(),
+ ],
+ ),
);
// Adds the appropriate opacity under the magnifier if the background
// color is transparent.
diff --git a/packages/flutter/lib/src/cupertino/text_theme.dart b/packages/flutter/lib/src/cupertino/text_theme.dart
index edf924d..ba5a6b8 100644
--- a/packages/flutter/lib/src/cupertino/text_theme.dart
+++ b/packages/flutter/lib/src/cupertino/text_theme.dart
@@ -83,6 +83,46 @@
color: CupertinoColors.white,
);
+// Eyeballed value since it's not documented in https://developer.apple.com/design/resources/.
+const TextStyle _kDefaultPickerLightTextStyle = TextStyle(
+ inherit: false,
+ fontFamily: '.SF Pro Display',
+ fontSize: 25.0,
+ fontWeight: FontWeight.w400,
+ letterSpacing: -0.41,
+ color: CupertinoColors.black,
+);
+
+// Eyeballed value since it's not documented in https://developer.apple.com/design/resources/.
+const TextStyle _kDefaultPickerDarkTextStyle = TextStyle(
+ inherit: false,
+ fontFamily: '.SF Pro Display',
+ fontSize: 25.0,
+ fontWeight: FontWeight.w400,
+ letterSpacing: -0.41,
+ color: CupertinoColors.white,
+);
+
+// Eyeballed value since it's not documented in https://developer.apple.com/design/resources/.
+const TextStyle _kDefaultDateTimePickerLightTextStyle = TextStyle(
+ inherit: false,
+ fontFamily: '.SF Pro Display',
+ fontSize: 21,
+ fontWeight: FontWeight.w300,
+ letterSpacing: -1.05,
+ color: CupertinoColors.black,
+);
+
+// Eyeballed value since it's not documented in https://developer.apple.com/design/resources/.
+const TextStyle _kDefaultDateTimePickerDarkTextStyle = TextStyle(
+ inherit: false,
+ fontFamily: '.SF Pro Display',
+ fontSize: 21,
+ fontWeight: FontWeight.w300,
+ letterSpacing: -1.05,
+ color: CupertinoColors.white,
+);
+
/// Cupertino typography theme in a [CupertinoThemeData].
@immutable
class CupertinoTextThemeData extends Diagnosticable {
@@ -104,6 +144,8 @@
TextStyle navTitleTextStyle,
TextStyle navLargeTitleTextStyle,
TextStyle navActionTextStyle,
+ TextStyle pickerTextStyle,
+ TextStyle dateTimePickerTextStyle,
}) : _primaryColor = primaryColor ?? CupertinoColors.activeBlue,
_brightness = brightness,
_textStyle = textStyle,
@@ -111,7 +153,9 @@
_tabLabelTextStyle = tabLabelTextStyle,
_navTitleTextStyle = navTitleTextStyle,
_navLargeTitleTextStyle = navLargeTitleTextStyle,
- _navActionTextStyle = navActionTextStyle;
+ _navActionTextStyle = navActionTextStyle,
+ _pickerTextStyle = pickerTextStyle,
+ _dateTimePickerTextStyle = dateTimePickerTextStyle;
final Color _primaryColor;
final Brightness _brightness;
@@ -155,6 +199,20 @@
);
}
+ final TextStyle _pickerTextStyle;
+ /// Typography of pickers.
+ TextStyle get pickerTextStyle {
+ return _pickerTextStyle ??
+ (_isLight ? _kDefaultPickerLightTextStyle : _kDefaultPickerDarkTextStyle);
+ }
+
+ final TextStyle _dateTimePickerTextStyle;
+ /// Typography of date time pickers.
+ TextStyle get dateTimePickerTextStyle {
+ return _dateTimePickerTextStyle ??
+ (_isLight ? _kDefaultDateTimePickerLightTextStyle : _kDefaultDateTimePickerDarkTextStyle);
+ }
+
/// Returns a copy of the current [CupertinoTextThemeData] instance with
/// specified overrides.
CupertinoTextThemeData copyWith({
@@ -166,6 +224,8 @@
TextStyle navTitleTextStyle,
TextStyle navLargeTitleTextStyle,
TextStyle navActionTextStyle,
+ TextStyle pickerTextStyle,
+ TextStyle dateTimePickerTextStyle,
}) {
return CupertinoTextThemeData(
primaryColor: primaryColor ?? _primaryColor,
@@ -176,6 +236,8 @@
navTitleTextStyle: navTitleTextStyle ?? _navTitleTextStyle,
navLargeTitleTextStyle: navLargeTitleTextStyle ?? _navLargeTitleTextStyle,
navActionTextStyle: navActionTextStyle ?? _navActionTextStyle,
+ pickerTextStyle: pickerTextStyle ?? _pickerTextStyle,
+ dateTimePickerTextStyle: dateTimePickerTextStyle ?? _dateTimePickerTextStyle,
);
}
}
diff --git a/packages/flutter/lib/src/rendering/list_wheel_viewport.dart b/packages/flutter/lib/src/rendering/list_wheel_viewport.dart
index a222826..7b2f7b2 100644
--- a/packages/flutter/lib/src/rendering/list_wheel_viewport.dart
+++ b/packages/flutter/lib/src/rendering/list_wheel_viewport.dart
@@ -137,10 +137,11 @@
@required ViewportOffset offset,
double diameterRatio = defaultDiameterRatio,
double perspective = defaultPerspective,
- double offAxisFraction = 0.0,
+ double offAxisFraction = 0,
bool useMagnifier = false,
- double magnification = 1.0,
+ double magnification = 1,
@required double itemExtent,
+ double squeeze = 1,
bool clipToSize = true,
bool renderChildrenOutsideViewport = false,
List<RenderBox> children,
@@ -156,6 +157,8 @@
assert(magnification != null),
assert(magnification > 0),
assert(itemExtent != null),
+ assert(squeeze != null),
+ assert(squeeze > 0),
assert(itemExtent > 0),
assert(clipToSize != null),
assert(renderChildrenOutsideViewport != null),
@@ -170,6 +173,7 @@
_useMagnifier = useMagnifier,
_magnification = magnification,
_itemExtent = itemExtent,
+ _squeeze = squeeze,
_clipToSize = clipToSize,
_renderChildrenOutsideViewport = renderChildrenOutsideViewport {
addAll(children);
@@ -381,6 +385,39 @@
markNeedsLayout();
}
+
+ /// {@template flutter.rendering.wheelList.squeeze}
+ /// The angular compactness of the children on the wheel.
+ ///
+ /// This denotes a ratio of the number of children on the wheel vs the number
+ /// of children that would fit on a flat list of equivalent size, assuming
+ /// [diameterRatio] of 1.
+ ///
+ /// For instance, if this RenderListWheelViewport has a height of 100px and
+ /// [itemExtent] is 20px, 5 items would fit on an equivalent flat list.
+ /// With a [squeeze] of 1, 5 items would also be shown in the
+ /// RenderListWheelViewport. With a [squeeze] of 2, 10 items would be shown
+ /// in the RenderListWheelViewport.
+ ///
+ /// Changing this value will change the number of children built and shown
+ /// inside the wheel.
+ ///
+ /// Must not be null and must be positive.
+ /// {@endtemplate}
+ ///
+ /// Defaults to 1.
+ double get squeeze => _squeeze;
+ double _squeeze;
+ set squeeze(double value) {
+ assert(value != null);
+ assert(value > 0);
+ if (value == _squeeze)
+ return;
+ _squeeze = value;
+ markNeedsLayout();
+ markNeedsSemanticsUpdate();
+ }
+
/// {@template flutter.rendering.wheelList.clipToSize}
/// Whether to clip painted children to the inside of this viewport.
///
@@ -614,7 +651,7 @@
// The height, in pixel, that children will be visible and might be laid out
// and painted.
- double visibleHeight = size.height;
+ double visibleHeight = size.height * _squeeze;
// If renderChildrenOutsideViewport is true, we spawn extra children by
// doubling the visibility range, those that are in the backside of the
// cylinder won't be painted anyway.
@@ -769,7 +806,7 @@
// Get child's center as a fraction of the viewport's height.
final double fractionalY =
(untransformedPaintingCoordinates.dy + _itemExtent / 2.0) / size.height;
- final double angle = -(fractionalY - 0.5) * 2.0 * _maxVisibleRadian;
+ final double angle = -(fractionalY - 0.5) * 2.0 * _maxVisibleRadian / squeeze;
// Don't paint the backside of the cylinder when
// renderChildrenOutsideViewport is true. Otherwise, only children within
// suitable angles (via _first/lastVisibleLayoutOffset) reach the paint
diff --git a/packages/flutter/lib/src/widgets/list_wheel_scroll_view.dart b/packages/flutter/lib/src/widgets/list_wheel_scroll_view.dart
index 50c8574..c5dad5a 100644
--- a/packages/flutter/lib/src/widgets/list_wheel_scroll_view.dart
+++ b/packages/flutter/lib/src/widgets/list_wheel_scroll_view.dart
@@ -576,6 +576,7 @@
this.useMagnifier = false,
this.magnification = 1.0,
@required this.itemExtent,
+ this.squeeze = 1.0,
this.onSelectedItemChanged,
this.clipToSize = true,
this.renderChildrenOutsideViewport = false,
@@ -589,6 +590,8 @@
assert(magnification > 0),
assert(itemExtent != null),
assert(itemExtent > 0),
+ assert(squeeze != null),
+ assert(squeeze > 0),
assert(clipToSize != null),
assert(renderChildrenOutsideViewport != null),
assert(
@@ -610,6 +613,7 @@
this.useMagnifier = false,
this.magnification = 1.0,
@required this.itemExtent,
+ this.squeeze = 1.0,
this.onSelectedItemChanged,
this.clipToSize = true,
this.renderChildrenOutsideViewport = false,
@@ -623,6 +627,8 @@
assert(magnification > 0),
assert(itemExtent != null),
assert(itemExtent > 0),
+ assert(squeeze != null),
+ assert(squeeze > 0),
assert(clipToSize != null),
assert(renderChildrenOutsideViewport != null),
assert(
@@ -675,6 +681,11 @@
/// positive.
final double itemExtent;
+ /// {@macro flutter.rendering.wheelList.squeeze}
+ ///
+ /// Defaults to 1.
+ final double squeeze;
+
/// On optional listener that's called when the centered item changes.
final ValueChanged<int> onSelectedItemChanged;
@@ -747,6 +758,7 @@
useMagnifier: widget.useMagnifier,
magnification: widget.magnification,
itemExtent: widget.itemExtent,
+ squeeze: widget.squeeze,
clipToSize: widget.clipToSize,
renderChildrenOutsideViewport: widget.renderChildrenOutsideViewport,
offset: offset,
@@ -941,6 +953,7 @@
this.useMagnifier = false,
this.magnification = 1.0,
@required this.itemExtent,
+ this.squeeze = 1.0,
this.clipToSize = true,
this.renderChildrenOutsideViewport = false,
@required this.offset,
@@ -954,6 +967,8 @@
assert(perspective <= 0.01, RenderListWheelViewport.perspectiveTooHighMessage),
assert(itemExtent != null),
assert(itemExtent > 0),
+ assert(squeeze != null),
+ assert(squeeze > 0),
assert(clipToSize != null),
assert(renderChildrenOutsideViewport != null),
assert(
@@ -980,6 +995,11 @@
/// {@macro flutter.rendering.wheelList.itemExtent}
final double itemExtent;
+ /// {@macro flutter.rendering.wheelList.squeeze}
+ ///
+ /// Defaults to 1.
+ final double squeeze;
+
/// {@macro flutter.rendering.wheelList.clipToSize}
final bool clipToSize;
@@ -1008,6 +1028,7 @@
useMagnifier: useMagnifier,
magnification: magnification,
itemExtent: itemExtent,
+ squeeze: squeeze,
clipToSize: clipToSize,
renderChildrenOutsideViewport: renderChildrenOutsideViewport,
);
@@ -1023,6 +1044,7 @@
..useMagnifier = useMagnifier
..magnification = magnification
..itemExtent = itemExtent
+ ..squeeze = squeeze
..clipToSize = clipToSize
..renderChildrenOutsideViewport = renderChildrenOutsideViewport;
}
diff --git a/packages/flutter/test/cupertino/date_picker_test.dart b/packages/flutter/test/cupertino/date_picker_test.dart
index e387d0b..83a9f63 100644
--- a/packages/flutter/test/cupertino/date_picker_test.dart
+++ b/packages/flutter/test/cupertino/date_picker_test.dart
@@ -123,13 +123,13 @@
expect(tester.getTopLeft(find.text('30')).dx > lastOffset.dx, true);
lastOffset = tester.getTopLeft(find.text('30'));
- expect(tester.getTopLeft(find.text('min')).dx > lastOffset.dx, true);
- lastOffset = tester.getTopLeft(find.text('min'));
+ expect(tester.getTopLeft(find.text('min.')).dx > lastOffset.dx, true);
+ lastOffset = tester.getTopLeft(find.text('min.'));
expect(tester.getTopLeft(find.text('59')).dx > lastOffset.dx, true);
lastOffset = tester.getTopLeft(find.text('59'));
- expect(tester.getTopLeft(find.text('sec')).dx > lastOffset.dx, true);
+ expect(tester.getTopLeft(find.text('sec.')).dx > lastOffset.dx, true);
});
testWidgets('columns are ordered correctly when text direction is rtl', (WidgetTester tester) async {
@@ -153,13 +153,13 @@
expect(tester.getTopLeft(find.text('30')).dx > lastOffset.dx, false);
lastOffset = tester.getTopLeft(find.text('30'));
- expect(tester.getTopLeft(find.text('min')).dx > lastOffset.dx, false);
- lastOffset = tester.getTopLeft(find.text('min'));
+ expect(tester.getTopLeft(find.text('min.')).dx > lastOffset.dx, false);
+ lastOffset = tester.getTopLeft(find.text('min.'));
expect(tester.getTopLeft(find.text('59')).dx > lastOffset.dx, false);
lastOffset = tester.getTopLeft(find.text('59'));
- expect(tester.getTopLeft(find.text('sec')).dx > lastOffset.dx, false);
+ expect(tester.getTopLeft(find.text('sec.')).dx > lastOffset.dx, false);
});
testWidgets('width of picker is consistent', (WidgetTester tester) async {
@@ -178,7 +178,7 @@
// Distance between the first column and the last column.
final double distance =
- tester.getCenter(find.text('sec')).dx - tester.getCenter(find.text('12')).dx;
+ tester.getCenter(find.text('sec.')).dx - tester.getCenter(find.text('12')).dx;
await tester.pumpWidget(
CupertinoApp(
@@ -195,7 +195,7 @@
// Distance between the first and the last column should be the same.
expect(
- tester.getCenter(find.text('sec')).dx - tester.getCenter(find.text('12')).dx,
+ tester.getCenter(find.text('sec.')).dx - tester.getCenter(find.text('12')).dx,
distance,
);
});
@@ -270,14 +270,16 @@
DateTime newDateTime;
await tester.pumpWidget(
CupertinoApp(
- home: SizedBox(
- width: 400,
- height: 400,
- child: CupertinoDatePicker(
- onDateTimeChanged: (DateTime d) => newDateTime = d,
- initialDateTime: DateTime(2018, 10, 10, 10, 3),
- minuteInterval: 3,
- )
+ home: Center(
+ child: SizedBox(
+ width: 400,
+ height: 400,
+ child: CupertinoDatePicker(
+ onDateTimeChanged: (DateTime d) => newDateTime = d,
+ initialDateTime: DateTime(2018, 10, 10, 10, 3),
+ minuteInterval: 3,
+ )
+ ),
)
)
);
@@ -295,13 +297,15 @@
DateTime selectedDateTime;
await tester.pumpWidget(
CupertinoApp(
- home: SizedBox(
- height: 400.0,
- width: 400.0,
- child: CupertinoDatePicker(
- mode: CupertinoDatePickerMode.dateAndTime,
- onDateTimeChanged: (DateTime dateTime) => selectedDateTime = dateTime,
- initialDateTime: DateTime(2018, 1, 1, 10, 30),
+ home: Center(
+ child: SizedBox(
+ height: 400.0,
+ width: 400.0,
+ child: CupertinoDatePicker(
+ mode: CupertinoDatePickerMode.dateAndTime,
+ onDateTimeChanged: (DateTime dateTime) => selectedDateTime = dateTime,
+ initialDateTime: DateTime(2018, 1, 1, 10, 30),
+ ),
),
),
),
@@ -315,14 +319,16 @@
await tester.pumpWidget(
CupertinoApp(
- home: SizedBox(
- height: 400.0,
- width: 400.0,
- child: CupertinoDatePicker(
- mode: CupertinoDatePickerMode.dateAndTime,
- onDateTimeChanged: (DateTime dateTime) => selectedDateTime = dateTime,
- // Change the initial date, but it shouldn't affect the present state.
- initialDateTime: DateTime(2016, 4, 5, 15, 00),
+ home: Center(
+ child: SizedBox(
+ height: 400.0,
+ width: 400.0,
+ child: CupertinoDatePicker(
+ mode: CupertinoDatePickerMode.dateAndTime,
+ onDateTimeChanged: (DateTime dateTime) => selectedDateTime = dateTime,
+ // Change the initial date, but it shouldn't affect the present state.
+ initialDateTime: DateTime(2016, 4, 5, 15, 00),
+ ),
),
),
),
@@ -339,13 +345,15 @@
testWidgets('date picker has expected string', (WidgetTester tester) async {
await tester.pumpWidget(
CupertinoApp(
- home: SizedBox(
- height: 400.0,
- width: 400.0,
- child: CupertinoDatePicker(
- mode: CupertinoDatePickerMode.date,
- onDateTimeChanged: (_) { },
- initialDateTime: DateTime(2018, 9, 15, 0, 0),
+ home: Center(
+ child: SizedBox(
+ height: 400.0,
+ width: 400.0,
+ child: CupertinoDatePicker(
+ mode: CupertinoDatePickerMode.date,
+ onDateTimeChanged: (_) { },
+ initialDateTime: DateTime(2018, 9, 15, 0, 0),
+ ),
),
),
),
@@ -359,13 +367,15 @@
testWidgets('datetime picker has expected string', (WidgetTester tester) async {
await tester.pumpWidget(
CupertinoApp(
- home: SizedBox(
- height: 400.0,
- width: 400.0,
- child: CupertinoDatePicker(
- mode: CupertinoDatePickerMode.dateAndTime,
- onDateTimeChanged: (_) { },
- initialDateTime: DateTime(2018, 9, 15, 3, 14),
+ home: Center(
+ child: SizedBox(
+ height: 400.0,
+ width: 400.0,
+ child: CupertinoDatePicker(
+ mode: CupertinoDatePickerMode.dateAndTime,
+ onDateTimeChanged: (_) { },
+ initialDateTime: DateTime(2018, 9, 15, 3, 14),
+ ),
),
),
),
@@ -397,13 +407,15 @@
await tester.pumpWidget(
CupertinoApp(
- home: SizedBox(
- height: 400.0,
- width: 800.0,
- child: CupertinoDatePicker(
- mode: CupertinoDatePickerMode.dateAndTime,
- onDateTimeChanged: (_) { },
- initialDateTime: DateTime(2018, 1, 1, 10, 30),
+ home: Center(
+ child: SizedBox(
+ height: 400.0,
+ width: 800.0,
+ child: CupertinoDatePicker(
+ mode: CupertinoDatePickerMode.dateAndTime,
+ onDateTimeChanged: (_) { },
+ initialDateTime: DateTime(2018, 1, 1, 10, 30),
+ ),
),
),
),
@@ -419,13 +431,15 @@
testWidgets('width of picker in date mode is consistent', (WidgetTester tester) async {
await tester.pumpWidget(
CupertinoApp(
- home: SizedBox(
- height: 400.0,
- width: 400.0,
- child: CupertinoDatePicker(
- mode: CupertinoDatePickerMode.date,
- onDateTimeChanged: (_) { },
- initialDateTime: DateTime(2018, 1, 1, 10, 30),
+ home: Center(
+ child: SizedBox(
+ height: 400.0,
+ width: 400.0,
+ child: CupertinoDatePicker(
+ mode: CupertinoDatePickerMode.date,
+ onDateTimeChanged: (_) { },
+ initialDateTime: DateTime(2018, 1, 1, 10, 30),
+ ),
),
),
),
@@ -437,13 +451,15 @@
await tester.pumpWidget(
CupertinoApp(
- home: SizedBox(
- height: 400.0,
- width: 800.0,
- child: CupertinoDatePicker(
- mode: CupertinoDatePickerMode.date,
- onDateTimeChanged: (_) { },
- initialDateTime: DateTime(2018, 1, 1, 10, 30),
+ home: Center(
+ child: SizedBox(
+ height: 400.0,
+ width: 800.0,
+ child: CupertinoDatePicker(
+ mode: CupertinoDatePickerMode.date,
+ onDateTimeChanged: (_) { },
+ initialDateTime: DateTime(2018, 1, 1, 10, 30),
+ ),
),
),
),
@@ -459,13 +475,15 @@
testWidgets('width of picker in time mode is consistent', (WidgetTester tester) async {
await tester.pumpWidget(
CupertinoApp(
- home: SizedBox(
- height: 400.0,
- width: 400.0,
- child: CupertinoDatePicker(
- mode: CupertinoDatePickerMode.time,
- onDateTimeChanged: (_) { },
- initialDateTime: DateTime(2018, 1, 1, 10, 30),
+ home: Center(
+ child: SizedBox(
+ height: 400.0,
+ width: 400.0,
+ child: CupertinoDatePicker(
+ mode: CupertinoDatePickerMode.time,
+ onDateTimeChanged: (_) { },
+ initialDateTime: DateTime(2018, 1, 1, 10, 30),
+ ),
),
),
),
@@ -477,13 +495,15 @@
await tester.pumpWidget(
CupertinoApp(
- home: SizedBox(
- height: 400.0,
- width: 800.0,
- child: CupertinoDatePicker(
- mode: CupertinoDatePickerMode.time,
- onDateTimeChanged: (_) { },
- initialDateTime: DateTime(2018, 1, 1, 10, 30),
+ home: Center(
+ child: SizedBox(
+ height: 400.0,
+ width: 800.0,
+ child: CupertinoDatePicker(
+ mode: CupertinoDatePickerMode.time,
+ onDateTimeChanged: (_) { },
+ initialDateTime: DateTime(2018, 1, 1, 10, 30),
+ ),
),
),
),
@@ -500,15 +520,17 @@
DateTime date;
await tester.pumpWidget(
CupertinoApp(
- home: SizedBox(
- height: 400.0,
- width: 400.0,
- child: CupertinoDatePicker(
- mode: CupertinoDatePickerMode.date,
- onDateTimeChanged: (DateTime newDate) {
- date = newDate;
- },
- initialDateTime: DateTime(2018, 3, 30),
+ home: Center(
+ child: SizedBox(
+ height: 400.0,
+ width: 400.0,
+ child: CupertinoDatePicker(
+ mode: CupertinoDatePickerMode.date,
+ onDateTimeChanged: (DateTime newDate) {
+ date = newDate;
+ },
+ initialDateTime: DateTime(2018, 3, 30),
+ ),
),
),
),
@@ -539,15 +561,17 @@
DateTime date;
await tester.pumpWidget(
CupertinoApp(
- home: SizedBox(
- height: 400.0,
- width: 400.0,
- child: CupertinoDatePicker(
- mode: CupertinoDatePickerMode.date,
- onDateTimeChanged: (DateTime newDate) {
- date = newDate;
- },
- initialDateTime: DateTime(2018, 2, 27), // 2018 has 28 days in Feb.
+ home: Center(
+ child: SizedBox(
+ height: 400.0,
+ width: 400.0,
+ child: CupertinoDatePicker(
+ mode: CupertinoDatePickerMode.date,
+ onDateTimeChanged: (DateTime newDate) {
+ date = newDate;
+ },
+ initialDateTime: DateTime(2018, 2, 27), // 2018 has 28 days in Feb.
+ ),
),
),
),
@@ -592,15 +616,17 @@
DateTime date;
await tester.pumpWidget(
CupertinoApp(
- home: SizedBox(
- height: 400.0,
- width: 400.0,
- child: CupertinoDatePicker(
- mode: CupertinoDatePickerMode.time,
- onDateTimeChanged: (DateTime newDate) {
- date = newDate;
- },
- initialDateTime: DateTime(2019, 1, 1, 0, 15),
+ home: Center(
+ child: SizedBox(
+ height: 400.0,
+ width: 400.0,
+ child: CupertinoDatePicker(
+ mode: CupertinoDatePickerMode.time,
+ onDateTimeChanged: (DateTime newDate) {
+ date = newDate;
+ },
+ initialDateTime: DateTime(2019, 1, 1, 0, 15),
+ ),
),
),
),
@@ -618,15 +644,17 @@
DateTime date;
await tester.pumpWidget(
CupertinoApp(
- home: SizedBox(
- height: 400.0,
- width: 400.0,
- child: CupertinoDatePicker(
- mode: CupertinoDatePickerMode.time,
- onDateTimeChanged: (DateTime newDate) {
- date = newDate;
- },
- initialDateTime: DateTime(2019, 1, 1, 12, 15),
+ home: Center(
+ child: SizedBox(
+ height: 400.0,
+ width: 400.0,
+ child: CupertinoDatePicker(
+ mode: CupertinoDatePickerMode.time,
+ onDateTimeChanged: (DateTime newDate) {
+ date = newDate;
+ },
+ initialDateTime: DateTime(2019, 1, 1, 12, 15),
+ ),
),
),
),
@@ -644,16 +672,18 @@
DateTime date;
await tester.pumpWidget(
CupertinoApp(
- home: SizedBox(
- height: 400.0,
- width: 400.0,
- child: CupertinoDatePicker(
- use24hFormat: true,
- mode: CupertinoDatePickerMode.time,
- onDateTimeChanged: (DateTime newDate) {
- date = newDate;
- },
- initialDateTime: DateTime(2019, 1, 1, 12, 25),
+ home: Center(
+ child: SizedBox(
+ height: 400.0,
+ width: 400.0,
+ child: CupertinoDatePicker(
+ use24hFormat: true,
+ mode: CupertinoDatePickerMode.time,
+ onDateTimeChanged: (DateTime newDate) {
+ date = newDate;
+ },
+ initialDateTime: DateTime(2019, 1, 1, 12, 25),
+ ),
),
),
),
@@ -672,15 +702,17 @@
DateTime date;
await tester.pumpWidget(
CupertinoApp(
- home: SizedBox(
- height: 400.0,
- width: 400.0,
- child: CupertinoDatePicker(
- mode: CupertinoDatePickerMode.time,
- onDateTimeChanged: (DateTime newDate) {
- date = newDate;
- },
- initialDateTime: DateTime(2019, 1, 1, 3),
+ home: Center(
+ child: SizedBox(
+ height: 400.0,
+ width: 400.0,
+ child: CupertinoDatePicker(
+ mode: CupertinoDatePickerMode.time,
+ onDateTimeChanged: (DateTime newDate) {
+ date = newDate;
+ },
+ initialDateTime: DateTime(2019, 1, 1, 3),
+ ),
),
),
),
@@ -719,15 +751,17 @@
DateTime date;
await tester.pumpWidget(
CupertinoApp(
- home: SizedBox(
- height: 400.0,
- width: 400.0,
- child: CupertinoDatePicker(
- mode: CupertinoDatePickerMode.time,
- onDateTimeChanged: (DateTime newDate) {
- date = newDate;
- },
- initialDateTime: DateTime(2018, 1, 1, 11, 59),
+ home: Center(
+ child: SizedBox(
+ height: 400.0,
+ width: 400.0,
+ child: CupertinoDatePicker(
+ mode: CupertinoDatePickerMode.time,
+ onDateTimeChanged: (DateTime newDate) {
+ date = newDate;
+ },
+ initialDateTime: DateTime(2018, 1, 1, 11, 59),
+ ),
),
),
),
@@ -763,6 +797,67 @@
expect(date, DateTime(2018, 1, 1, 15, 59));
});
+
+ testWidgets('date picker given too narrow space horizontally shows message', (WidgetTester tester) async {
+ await tester.pumpWidget(
+ CupertinoApp(
+ home: Center(
+ child: SizedBox(
+ // This is too small to draw the picker out fully.
+ width: 100,
+ child: CupertinoDatePicker(
+ mode: CupertinoDatePickerMode.dateAndTime,
+ initialDateTime: DateTime(2019, 1, 1, 4),
+ onDateTimeChanged: (_) {},
+ )
+ ),
+ )
+ )
+ );
+
+ final dynamic exception = tester.takeException();
+ expect(exception, isAssertionError);
+ expect(
+ exception.toString(),
+ contains('Insufficient horizontal space to render the CupertinoDatePicker'),
+ );
+ });
+
+ testWidgets('DatePicker golden tests', (WidgetTester tester) async {
+ await tester.pumpWidget(
+ CupertinoApp(
+ home: Center(
+ child: SizedBox(
+ width: 400,
+ height: 400,
+ child: RepaintBoundary(
+ child: CupertinoDatePicker(
+ mode: CupertinoDatePickerMode.dateAndTime,
+ initialDateTime: DateTime(2019, 1, 1, 4),
+ onDateTimeChanged: (_) {},
+ ),
+ )
+ ),
+ )
+ )
+ );
+
+ await expectLater(
+ find.byType(CupertinoDatePicker),
+ matchesGoldenFile('date_picker_test.datetime.initial.1.png'),
+ skip: !Platform.isLinux
+ );
+
+ // Slightly drag the hour component to make the current hour off-center.
+ await tester.drag(find.text('4'), Offset(0, _kRowOffset.dy / 2));
+ await tester.pump();
+
+ await expectLater(
+ find.byType(CupertinoDatePicker),
+ matchesGoldenFile('date_picker_test.datetime.drag.1.png'),
+ skip: !Platform.isLinux
+ );
+ });
});
testWidgets('scrollController can be removed or added', (WidgetTester tester) async {
@@ -838,37 +933,6 @@
expect(lastSelectedItem, 1);
handle.dispose();
});
-
- testWidgets('DatePicker golden tests', (WidgetTester tester) async {
- await tester.pumpWidget(
- CupertinoApp(
- home: SizedBox(
- width: 200,
- child: CupertinoDatePicker(
- mode: CupertinoDatePickerMode.dateAndTime,
- initialDateTime: DateTime(2019, 1, 1, 4),
- onDateTimeChanged: (_) {},
- )
- )
- )
- );
-
- await expectLater(
- find.byType(CupertinoDatePicker),
- matchesGoldenFile('date_picker_test.datetime.initial.png'),
- skip: !Platform.isLinux
- );
-
- // Slightly drag the hour component to make the current hour off-center.
- await tester.drag(find.text('4'), Offset(0, _kRowOffset.dy / 2));
- await tester.pump();
-
- await expectLater(
- find.byType(CupertinoDatePicker),
- matchesGoldenFile('date_picker_test.datetime.drag.png'),
- skip: !Platform.isLinux
- );
- });
}
Widget _buildPicker({ FixedExtentScrollController controller, ValueChanged<int> onSelectedItemChanged }) {
diff --git a/packages/flutter/test/cupertino/picker_test.dart b/packages/flutter/test/cupertino/picker_test.dart
index fcabcb1..cba11ac 100644
--- a/packages/flutter/test/cupertino/picker_test.dart
+++ b/packages/flutter/test/cupertino/picker_test.dart
@@ -3,10 +3,47 @@
// found in the LICENSE file.
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
+import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
+ testWidgets('Picker respects theme styling', (WidgetTester tester) async {
+ await tester.pumpWidget(
+ CupertinoApp(
+ home: Align(
+ alignment: Alignment.topLeft,
+ child: SizedBox(
+ height: 300.0,
+ width: 300.0,
+ child: CupertinoPicker(
+ itemExtent: 50.0,
+ onSelectedItemChanged: (_) { },
+ children: List<Widget>.generate(3, (int index) {
+ return Container(
+ height: 50.0,
+ width: 300.0,
+ child: Text(index.toString()),
+ );
+ }),
+ ),
+ ),
+ ),
+ ),
+ );
+
+ final RenderParagraph paragraph = tester.renderObject(find.text('1'));
+
+ expect(paragraph.text.style, const TextStyle(
+ inherit: false,
+ fontFamily: '.SF Pro Display',
+ fontSize: 25.0,
+ fontWeight: FontWeight.w400,
+ letterSpacing: -0.41,
+ color: CupertinoColors.black,
+ ));
+ });
+
group('layout', () {
testWidgets('selected item is in the middle', (WidgetTester tester) async {
final FixedExtentScrollController controller =
diff --git a/packages/flutter/test/widgets/list_wheel_scroll_view_test.dart b/packages/flutter/test/widgets/list_wheel_scroll_view_test.dart
index ef28545..6bf4950 100644
--- a/packages/flutter/test/widgets/list_wheel_scroll_view_test.dart
+++ b/packages/flutter/test/widgets/list_wheel_scroll_view_test.dart
@@ -349,6 +349,51 @@
// value of childCount should be 4.
expect(viewport.childCount, 4);
});
+
+ testWidgets('a tighter squeeze lays out more children', (WidgetTester tester) async {
+ final FixedExtentScrollController controller =
+ FixedExtentScrollController(initialItem: 10);
+
+ await tester.pumpWidget(
+ Directionality(
+ textDirection: TextDirection.ltr,
+ child: ListWheelScrollView(
+ controller: controller,
+ itemExtent: 100.0,
+ onSelectedItemChanged: (_) { },
+ children: List<Widget>.generate(20, (int index) {
+ return Text(index.toString());
+ }),
+ ),
+ )
+ );
+
+ final RenderListWheelViewport viewport = tester.firstRenderObject(find.byType(Text)).parent.parent;
+
+ // The screen is vertically 600px. Since the middle item is centered,
+ // half of the first and last items are visible, making 7 children visible.
+ expect(viewport.childCount, 7);
+
+ // Pump the same widget again but with double the squeeze.
+ await tester.pumpWidget(
+ Directionality(
+ textDirection: TextDirection.ltr,
+ child: ListWheelScrollView(
+ controller: controller,
+ itemExtent: 100.0,
+ squeeze: 2,
+ onSelectedItemChanged: (_) { },
+ children: List<Widget>.generate(20, (int index) {
+ return Text(index.toString());
+ }),
+ ),
+ )
+ );
+
+ // 12 instead of 6 children are laid out + 1 because the middle item is
+ // centered.
+ expect(viewport.childCount, 13);
+ });
});
group('pre-transform viewport', () {
diff --git a/packages/flutter_localizations/lib/src/l10n/cupertino_en.arb b/packages/flutter_localizations/lib/src/l10n/cupertino_en.arb
index 7d3cc73..76b4111 100644
--- a/packages/flutter_localizations/lib/src/l10n/cupertino_en.arb
+++ b/packages/flutter_localizations/lib/src/l10n/cupertino_en.arb
@@ -33,6 +33,11 @@
"description": "The abbreviation for post meridiem (after noon) shown in the time picker when it's not using the 24h format. Reference the text iOS uses such as in the iOS clock app."
},
+ "todayLabel": "Today",
+ "@todayLabel": {
+ "description": "A label shown in the date picker when the date is today."
+ },
+
"alertDialogLabel": "Alert",
"@alertDialogLabel": {
"description": "The accessibility audio announcement made when an iOS style alert dialog is opened."
@@ -45,15 +50,15 @@
"plural": "hour"
},
- "timerPickerMinuteLabelOne": "min",
- "timerPickerMinuteLabelOther": "min",
+ "timerPickerMinuteLabelOne": "min.",
+ "timerPickerMinuteLabelOther": "min.",
"@timerPickerMinuteLabel": {
"description": "The label adjacent to a minute integer number in a countdown timer. The reference abbreviation is what iOS does in the stock clock app's countdown timer.",
"plural": "minute"
},
- "timerPickerSecondLabelOne": "sec",
- "timerPickerSecondLabelOther": "sec",
+ "timerPickerSecondLabelOne": "sec.",
+ "timerPickerSecondLabelOther": "sec.",
"@timerPickerSecondLabel": {
"description": "The label adjacent to a second integer number in a countdown timer. The reference abbreviation is what iOS does in the stock clock app's countdown timer.",
"plural": "second"
diff --git a/packages/flutter_localizations/lib/src/l10n/cupertino_fr.arb b/packages/flutter_localizations/lib/src/l10n/cupertino_fr.arb
index 995c723..b3afc6e 100644
--- a/packages/flutter_localizations/lib/src/l10n/cupertino_fr.arb
+++ b/packages/flutter_localizations/lib/src/l10n/cupertino_fr.arb
@@ -7,6 +7,7 @@
"datePickerDateTimeOrder": "date_time_dayPeriod",
"anteMeridiemAbbreviation": "AM",
"postMeridiemAbbreviation": "PM",
+ "todayLabel": "aujourd'hui",
"alertDialogLabel": "Alerte",
"timerPickerHourLabelOne": "heure",
"timerPickerHourLabelOther": "heures",
diff --git a/packages/flutter_localizations/lib/src/l10n/generated_cupertino_localizations.dart b/packages/flutter_localizations/lib/src/l10n/generated_cupertino_localizations.dart
index 0114931..dbb2298 100644
--- a/packages/flutter_localizations/lib/src/l10n/generated_cupertino_localizations.dart
+++ b/packages/flutter_localizations/lib/src/l10n/generated_cupertino_localizations.dart
@@ -94,16 +94,19 @@
String get timerPickerHourLabelOther => r'hours';
@override
- String get timerPickerMinuteLabelOne => r'min';
+ String get timerPickerMinuteLabelOne => r'min.';
@override
- String get timerPickerMinuteLabelOther => r'min';
+ String get timerPickerMinuteLabelOther => r'min.';
@override
- String get timerPickerSecondLabelOne => r'sec';
+ String get timerPickerSecondLabelOne => r'sec.';
@override
- String get timerPickerSecondLabelOther => r'sec';
+ String get timerPickerSecondLabelOther => r'sec.';
+
+ @override
+ String get todayLabel => r'Today';
}
/// The translations for French (`fr`).
@@ -189,6 +192,9 @@
@override
String get timerPickerSecondLabelOther => r's';
+
+ @override
+ String get todayLabel => r'aujourd' "'" r'hui';
}
/// The set of supported languages, as language code strings.