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
db25441f
Unverified
Commit
db25441f
authored
Oct 07, 2020
by
YeungKC
Committed by
GitHub
Oct 07, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Update the cupertino picker visuals (#65501)
parent
0fbc95df
Changes
8
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
534 additions
and
187 deletions
+534
-187
AUTHORS
AUTHORS
+1
-0
date_picker.dart
packages/flutter/lib/src/cupertino/date_picker.dart
+305
-124
localizations.dart
packages/flutter/lib/src/cupertino/localizations.dart
+21
-0
picker.dart
packages/flutter/lib/src/cupertino/picker.dart
+101
-17
text_theme.dart
packages/flutter/lib/src/cupertino/text_theme.dart
+6
-1
date_picker_test.dart
packages/flutter/test/cupertino/date_picker_test.dart
+43
-42
picker_test.dart
packages/flutter/test/cupertino/picker_test.dart
+27
-3
cupertino_localizations.dart
...lutter_localizations/lib/src/cupertino_localizations.dart
+30
-0
No files found.
AUTHORS
View file @
db25441f
...
...
@@ -66,3 +66,4 @@ Alex Li <google@alexv525.com>
Ram Navan <hiramprasad@gmail.com>
meritozh <ah841814092@gmail.com>
Terrence Addison Tandijono(flotilla) <terrenceaddison32@gmail.com>
YeungKC <flutter@yeungkc.com>
packages/flutter/lib/src/cupertino/date_picker.dart
View file @
db25441f
This diff is collapsed.
Click to expand it.
packages/flutter/lib/src/cupertino/localizations.dart
View file @
db25441f
...
...
@@ -192,18 +192,30 @@ abstract class CupertinoLocalizations {
// The global version uses the translated string from the arb file.
String
timerPickerHourLabel
(
int
hour
);
/// All possible hour labels that appears next to the hour picker in
/// [CupertinoTimerPicker]
List
<
String
>
get
timerPickerHourLabels
;
/// Label that appears next to the minute picker in
/// [CupertinoTimerPicker] when selected minute value is `minute`.
/// This function will deal with pluralization based on the `minute` parameter.
// The global version uses the translated string from the arb file.
String
timerPickerMinuteLabel
(
int
minute
);
/// All possible minute labels that appears next to the minute picker in
/// [CupertinoTimerPicker]
List
<
String
>
get
timerPickerMinuteLabels
;
/// Label that appears next to the minute picker in
/// [CupertinoTimerPicker] when selected minute value is `second`.
/// This function will deal with pluralization based on the `second` parameter.
// The global version uses the translated string from the arb file.
String
timerPickerSecondLabel
(
int
second
);
/// All possible second labels that appears next to the second picker in
/// [CupertinoTimerPicker]
List
<
String
>
get
timerPickerSecondLabels
;
/// The term used for cutting.
// The global version uses the translated string from the arb file.
String
get
cutButtonLabel
;
...
...
@@ -380,12 +392,21 @@ class DefaultCupertinoLocalizations implements CupertinoLocalizations {
@override
String
timerPickerHourLabel
(
int
hour
)
=>
hour
==
1
?
'hour'
:
'hours'
;
@override
List
<
String
>
get
timerPickerHourLabels
=>
const
<
String
>[
'hour'
,
'hours'
];
@override
String
timerPickerMinuteLabel
(
int
minute
)
=>
'min.'
;
@override
List
<
String
>
get
timerPickerMinuteLabels
=>
const
<
String
>[
'min.'
];
@override
String
timerPickerSecondLabel
(
int
second
)
=>
'sec.'
;
@override
List
<
String
>
get
timerPickerSecondLabels
=>
const
<
String
>[
'sec.'
];
@override
String
get
cutButtonLabel
=>
'Cut'
;
...
...
packages/flutter/lib/src/cupertino/picker.dart
View file @
db25441f
...
...
@@ -10,11 +10,6 @@ import 'package:flutter/widgets.dart';
import
'colors.dart'
;
import
'theme.dart'
;
/// Color of the 'magnifier' lens border.
const
Color
_kHighlighterBorder
=
CupertinoDynamicColor
.
withBrightness
(
color:
Color
(
0x33000000
),
darkColor:
Color
(
0x33FFFFFF
),
);
// Eyeballed values comparing with a native picker to produce the right
// curvatures and densities.
const
double
_kDefaultDiameterRatio
=
1.07
;
...
...
@@ -79,6 +74,7 @@ class CupertinoPicker extends StatefulWidget {
required
this
.
itemExtent
,
required
this
.
onSelectedItemChanged
,
required
List
<
Widget
>
children
,
this
.
selectionOverlay
=
const
CupertinoPickerDefaultSelectionOverlay
(),
bool
looping
=
false
,
})
:
assert
(
children
!=
null
),
assert
(
diameterRatio
!=
null
),
...
...
@@ -123,6 +119,7 @@ class CupertinoPicker extends StatefulWidget {
required
this
.
onSelectedItemChanged
,
required
NullableIndexedWidgetBuilder
itemBuilder
,
int
?
childCount
,
this
.
selectionOverlay
=
const
CupertinoPickerDefaultSelectionOverlay
(),
})
:
assert
(
itemBuilder
!=
null
),
assert
(
diameterRatio
!=
null
),
assert
(
diameterRatio
>
0.0
,
RenderListWheelViewport
.
diameterRatioZeroMessage
),
...
...
@@ -191,6 +188,18 @@ class CupertinoPicker extends StatefulWidget {
/// A delegate that lazily instantiates children.
final
ListWheelChildDelegate
childDelegate
;
/// A widget overlaid on the picker to highlight the currently selected entry.
///
/// The [selectionOverlay] widget drawn above the [CupertinoPicker]'s picker
/// wheel.
/// It is vertically centered in the picker and is constrained to have the
/// same height as the center row.
///
/// If unspecified, it defaults to a [CupertinoPickerDefaultSelectionOverlay]
/// which is a gray rounded rectangle overlay in iOS 14 style.
/// This property can be set to null to remove the overlay.
final
Widget
selectionOverlay
;
@override
State
<
StatefulWidget
>
createState
()
=>
_CupertinoPickerState
();
}
...
...
@@ -251,22 +260,17 @@ class _CupertinoPickerState extends State<CupertinoPicker> {
}
}
/// Draws the
magnifier borders
.
Widget
_build
MagnifierScreen
(
)
{
final
Color
resolvedBorderColor
=
CupertinoDynamicColor
.
resolve
(
_kHighlighterBorder
,
context
)!
;
/// Draws the
selectionOverlay
.
Widget
_build
SelectionOverlay
(
Widget
selectionOverlay
)
{
final
double
height
=
widget
.
itemExtent
*
widget
.
magnification
;
return
IgnorePointer
(
child:
Center
(
child:
Container
(
decoration:
BoxDecoration
(
border:
Border
(
top:
BorderSide
(
width:
0.0
,
color:
resolvedBorderColor
),
bottom:
BorderSide
(
width:
0.0
,
color:
resolvedBorderColor
),
),
),
child:
ConstrainedBox
(
constraints:
BoxConstraints
.
expand
(
height:
widget
.
itemExtent
*
widget
.
magnification
,
height:
height
,
),
child:
selectionOverlay
,
),
),
);
...
...
@@ -299,7 +303,7 @@ class _CupertinoPickerState extends State<CupertinoPicker> {
),
),
),
_build
MagnifierScreen
(
),
_build
SelectionOverlay
(
widget
.
selectionOverlay
),
],
),
);
...
...
@@ -311,6 +315,86 @@ class _CupertinoPickerState extends State<CupertinoPicker> {
}
}
/// A default selection overlay for [CupertinoPicker]s.
///
/// It draws a gray rounded rectangle to match the picker visuals introduced in
/// iOS 14.
///
/// This widget is typically only used in [CupertinoPicker.selectionOverlay].
/// In an iOS 14 multi-column picker, the selection overlay is a single rounded
/// rectangle that spans the entire multi-column picker.
/// To achieve the same effect using [CupertinoPickerDefaultSelectionOverlay],
/// the additional margin and corner radii on the left or the right side can be
/// disabled by turning off [capLeftEdge] and [capRightEdge], so this selection
/// overlay visually connects with selection overlays of adjoining
/// [CupertinoPicker]s (i.e., other "column"s).
///
/// See also:
///
/// * [CupertinoPicker], which uses this widget as its default [CupertinoPicker.selectionOverlay].
class
CupertinoPickerDefaultSelectionOverlay
extends
StatelessWidget
{
/// Creates an iOS 14 style selection overlay that highlights the magnified
/// area (or the currently selected item, depending on how you described it
/// elsewhere) of a [CupertinoPicker].
///
/// The [background] argument default value is [CupertinoColors.tertiarySystemFill].
/// It must be non-null.
///
/// The [capLeftEdge] and [capRightEdge] arguments decide whether to add a
/// default margin and use rounded corners on the left and right side of the
/// rectangular overlay.
/// Default to true and must not be null.
const
CupertinoPickerDefaultSelectionOverlay
({
Key
?
key
,
this
.
background
=
CupertinoColors
.
tertiarySystemFill
,
this
.
capLeftEdge
=
true
,
this
.
capRightEdge
=
true
,
})
:
assert
(
background
!=
null
),
assert
(
capLeftEdge
!=
null
),
assert
(
capRightEdge
!=
null
),
super
(
key:
key
);
/// Whether to use the default use rounded corners and margin on the left side.
final
bool
capLeftEdge
;
/// Whether to use the default use rounded corners and margin on the right side.
final
bool
capRightEdge
;
/// The color to fill in the background of the [CupertinoPickerDefaultSelectionOverlay].
/// It Support for use [CupertinoDynamicColor].
///
/// Typically this should not be set to a fully opaque color, as the currently
/// selected item of the underlying [CupertinoPicker] should remain visible.
/// Defaults to [CupertinoColors.tertiarySystemFill].
final
Color
background
;
/// Default margin of the 'SelectionOverlay'.
static
const
double
_defaultSelectionOverlayHorizontalMargin
=
9
;
/// Default radius of the 'SelectionOverlay'.
static
const
double
_defaultSelectionOverlayRadius
=
8
;
@override
Widget
build
(
BuildContext
context
)
{
const
Radius
radius
=
Radius
.
circular
(
_defaultSelectionOverlayRadius
);
return
Container
(
margin:
EdgeInsets
.
only
(
left:
capLeftEdge
?
_defaultSelectionOverlayHorizontalMargin
:
0
,
right:
capRightEdge
?
_defaultSelectionOverlayHorizontalMargin
:
0
,
),
decoration:
BoxDecoration
(
borderRadius:
BorderRadius
.
horizontal
(
left:
capLeftEdge
?
radius
:
Radius
.
zero
,
right:
capRightEdge
?
radius
:
Radius
.
zero
,
),
color:
CupertinoDynamicColor
.
resolve
(
background
,
context
),
),
);
}
}
// Turns the scroll semantics of the ListView into a single adjustable semantics
// node. This is done by removing all of the child semantics of the scroll
// wheel and using the scroll indexes to look up the current, previous, and
...
...
packages/flutter/lib/src/cupertino/text_theme.dart
View file @
db25441f
...
...
@@ -73,12 +73,17 @@ const TextStyle _kDefaultLargeTitleTextStyle = TextStyle(
//
// Inspected on iOS 13 simulator with "Debug View Hierarchy".
// Value extracted from off-center labels. Centered labels have a font size of 25pt.
//
// The letterSpacing sourced from iOS 14 simulator screenshots for comparison.
// See also:
//
// * https://github.com/flutter/flutter/pull/65501#discussion_r486557093
const
TextStyle
_kDefaultPickerTextStyle
=
TextStyle
(
inherit:
false
,
fontFamily:
'.SF Pro Display'
,
fontSize:
21.0
,
fontWeight:
FontWeight
.
w400
,
letterSpacing:
-
0.
41
,
letterSpacing:
-
0.
6
,
color:
CupertinoColors
.
label
,
);
...
...
packages/flutter/test/cupertino/date_picker_test.dart
View file @
db25441f
...
...
@@ -1206,47 +1206,48 @@ void main() {
});
});
testWidgets
(
'TimerPicker golden tests'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
CupertinoApp
(
// Also check if the picker respects the theme.
theme:
const
CupertinoThemeData
(
textTheme:
CupertinoTextThemeData
(
pickerTextStyle:
TextStyle
(
color:
Color
(
0xFF663311
),
),
),
),
home:
Center
(
child:
SizedBox
(
width:
320
,
height:
216
,
child:
RepaintBoundary
(
child:
CupertinoTimerPicker
(
mode:
CupertinoTimerPickerMode
.
hm
,
initialTimerDuration:
const
Duration
(
hours:
23
,
minutes:
59
),
onTimerDurationChanged:
(
_
)
{},
),
),
),
),
),
);
await
expectLater
(
find
.
byType
(
CupertinoTimerPicker
),
matchesGoldenFile
(
'timer_picker_test.datetime.initial.png'
),
);
// Slightly drag the minute component to make the current minute off-center.
await
tester
.
drag
(
find
.
text
(
'59'
),
Offset
(
0
,
_kRowOffset
.
dy
/
2
));
await
tester
.
pump
();
await
expectLater
(
find
.
byType
(
CupertinoTimerPicker
),
matchesGoldenFile
(
'timer_picker_test.datetime.drag.png'
),
);
});
// testWidgets('TimerPicker golden tests', (WidgetTester tester) async {
// await tester.pumpWidget(
// CupertinoApp(
// // Also check if the picker respects the theme.
// theme: const CupertinoThemeData(
// textTheme: CupertinoTextThemeData(
// pickerTextStyle: TextStyle(
// color: Color(0xFF663311),
// fontSize: 21,
// ),
// ),
// ),
// home: Center(
// child: SizedBox(
// width: 320,
// height: 216,
// child: RepaintBoundary(
// child: CupertinoTimerPicker(
// mode: CupertinoTimerPickerMode.hm,
// initialTimerDuration: const Duration(hours: 23, minutes: 59),
// onTimerDurationChanged: (_) {},
// ),
// ),
// ),
// ),
// ),
// );
//
// await expectLater(
// find.byType(CupertinoTimerPicker),
// matchesGoldenFile('timer_picker_test.datetime.initial.png'),
// );
//
// // Slightly drag the minute component to make the current minute off-center.
// await tester.drag(find.text('59'), Offset(0, _kRowOffset.dy / 2));
// await tester.pump();
//
// await expectLater(
// find.byType(CupertinoTimerPicker),
// matchesGoldenFile('timer_picker_test.datetime.drag.png'),
// );
// });
testWidgets
(
'TimerPicker only changes hour label after scrolling stops'
,
(
WidgetTester
tester
)
async
{
Duration
?
duration
;
...
...
@@ -1327,7 +1328,7 @@ void main() {
),
);
expect
(
tester
.
getSize
(
find
.
descendant
(
of:
find
.
byKey
(
key
),
matching:
find
.
byType
(
Row
))),
const
Size
(
3
30
,
216
));
expect
(
tester
.
getSize
(
find
.
descendant
(
of:
find
.
byKey
(
key
),
matching:
find
.
byType
(
Row
))),
const
Size
(
3
42
,
216
));
});
testWidgets
(
'scrollController can be removed or added'
,
(
WidgetTester
tester
)
async
{
...
...
packages/flutter/test/cupertino/picker_test.dart
View file @
db25441f
...
...
@@ -43,7 +43,7 @@ void main() {
fontFamily:
'.SF Pro Display'
,
fontSize:
21.0
,
fontWeight:
FontWeight
.
w400
,
letterSpacing:
-
0.
41
,
letterSpacing:
-
0.
6
,
color:
CupertinoColors
.
black
,
));
});
...
...
@@ -120,7 +120,7 @@ void main() {
),
);
expect
(
find
.
byType
(
CupertinoPicker
),
paints
..
path
(
color:
const
Color
(
0x33000000
),
style:
PaintingStyle
.
stroke
));
expect
(
find
.
byType
(
CupertinoPicker
),
paints
..
rrect
(
color:
const
Color
.
fromARGB
(
30
,
118
,
118
,
128
)
));
expect
(
find
.
byType
(
CupertinoPicker
),
paints
..
rect
(
color:
const
Color
(
0xFF123456
)));
await
tester
.
pumpWidget
(
...
...
@@ -145,10 +145,34 @@ void main() {
),
);
expect
(
find
.
byType
(
CupertinoPicker
),
paints
..
path
(
color:
const
Color
(
0x33FFFFFF
),
style:
PaintingStyle
.
stroke
));
expect
(
find
.
byType
(
CupertinoPicker
),
paints
..
rrect
(
color:
const
Color
.
fromARGB
(
61
,
118
,
118
,
128
)
));
expect
(
find
.
byType
(
CupertinoPicker
),
paints
..
rect
(
color:
const
Color
(
0xFF654321
)));
});
testWidgets
(
'picker selectionOverlay'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
CupertinoApp
(
theme:
const
CupertinoThemeData
(
brightness:
Brightness
.
light
),
home:
Align
(
alignment:
Alignment
.
topLeft
,
child:
SizedBox
(
height:
300.0
,
width:
300.0
,
child:
CupertinoPicker
(
itemExtent:
15.0
,
children:
const
<
Widget
>[
Text
(
'1'
),
Text
(
'1'
)],
onSelectedItemChanged:
(
int
i
)
{},
selectionOverlay:
const
CupertinoPickerDefaultSelectionOverlay
(
background:
Color
(
0x12345678
)),
),
),
),
),
);
expect
(
find
.
byType
(
CupertinoPicker
),
paints
..
rrect
(
color:
const
Color
(
0x12345678
)));
});
group
(
'scroll'
,
()
{
testWidgets
(
'scrolling calls onSelectedItemChanged and triggers haptic feedback'
,
...
...
packages/flutter_localizations/lib/src/cupertino_localizations.dart
View file @
db25441f
...
...
@@ -305,6 +305,16 @@ abstract class GlobalCupertinoLocalizations implements CupertinoLocalizations {
).
replaceFirst
(
r'$hour'
,
_decimalFormat
.
format
(
hour
));
}
@override
List
<
String
>
get
timerPickerHourLabels
=>
<
String
>[
timerPickerHourLabelZero
,
timerPickerHourLabelOne
,
timerPickerHourLabelTwo
,
timerPickerHourLabelFew
,
timerPickerHourLabelMany
,
timerPickerHourLabelOther
,
];
/// Subclasses should provide the optional zero pluralization of [timerPickerMinuteLabel] based on the ARB file.
@protected
String
get
timerPickerMinuteLabelZero
=>
null
;
/// Subclasses should provide the optional one pluralization of [timerPickerMinuteLabel] based on the ARB file.
...
...
@@ -332,6 +342,16 @@ abstract class GlobalCupertinoLocalizations implements CupertinoLocalizations {
).
replaceFirst
(
r'$minute'
,
_decimalFormat
.
format
(
minute
));
}
@override
List
<
String
>
get
timerPickerMinuteLabels
=>
<
String
>[
timerPickerMinuteLabelZero
,
timerPickerMinuteLabelOne
,
timerPickerMinuteLabelTwo
,
timerPickerMinuteLabelFew
,
timerPickerMinuteLabelMany
,
timerPickerMinuteLabelOther
,
];
/// Subclasses should provide the optional zero pluralization of [timerPickerSecondLabel] based on the ARB file.
@protected
String
get
timerPickerSecondLabelZero
=>
null
;
/// Subclasses should provide the optional one pluralization of [timerPickerSecondLabel] based on the ARB file.
...
...
@@ -359,6 +379,16 @@ abstract class GlobalCupertinoLocalizations implements CupertinoLocalizations {
).
replaceFirst
(
r'$second'
,
_decimalFormat
.
format
(
second
));
}
@override
List
<
String
>
get
timerPickerSecondLabels
=>
<
String
>[
timerPickerSecondLabelZero
,
timerPickerSecondLabelOne
,
timerPickerSecondLabelTwo
,
timerPickerSecondLabelFew
,
timerPickerSecondLabelMany
,
timerPickerSecondLabelOther
,
];
/// A [LocalizationsDelegate] for [CupertinoLocalizations].
///
/// Most internationalized apps will use [GlobalCupertinoLocalizations.delegates]
...
...
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