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
6781576e
Unverified
Commit
6781576e
authored
Dec 22, 2022
by
Justin McCandless
Committed by
GitHub
Dec 22, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Reland iOS 16 context menu (#117234)
Updates the iOS text selection toolbar to look like iOS 16 (reland)
parent
abd5217f
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
134 additions
and
28 deletions
+134
-28
colors.dart
packages/flutter/lib/src/cupertino/colors.dart
+1
-1
text_selection_toolbar.dart
...ges/flutter/lib/src/cupertino/text_selection_toolbar.dart
+36
-8
text_selection_toolbar_button.dart
...tter/lib/src/cupertino/text_selection_toolbar_button.dart
+29
-16
text_field_test.dart
packages/flutter/test/cupertino/text_field_test.dart
+3
-3
text_selection_toolbar_test.dart
...s/flutter/test/cupertino/text_selection_toolbar_test.dart
+65
-0
No files found.
packages/flutter/lib/src/cupertino/colors.dart
View file @
6781576e
...
@@ -990,7 +990,7 @@ class CupertinoDynamicColor extends Color with Diagnosticable {
...
@@ -990,7 +990,7 @@ class CupertinoDynamicColor extends Color with Diagnosticable {
CupertinoDynamicColor
resolveFrom
(
BuildContext
context
)
{
CupertinoDynamicColor
resolveFrom
(
BuildContext
context
)
{
Brightness
brightness
=
Brightness
.
light
;
Brightness
brightness
=
Brightness
.
light
;
if
(
_isPlatformBrightnessDependent
)
{
if
(
_isPlatformBrightnessDependent
)
{
brightness
=
CupertinoTheme
.
maybeBrightnessOf
(
context
)
??
Brightness
.
light
;
brightness
=
CupertinoTheme
.
maybeBrightnessOf
(
context
)
??
Brightness
.
light
;
}
}
bool
isHighContrastEnabled
=
false
;
bool
isHighContrastEnabled
=
false
;
if
(
_isHighContrastDependent
)
{
if
(
_isHighContrastDependent
)
{
...
...
packages/flutter/lib/src/cupertino/text_selection_toolbar.dart
View file @
6781576e
...
@@ -5,11 +5,13 @@
...
@@ -5,11 +5,13 @@
import
'dart:collection'
;
import
'dart:collection'
;
import
'dart:ui'
as
ui
;
import
'dart:ui'
as
ui
;
import
'package:flutter/foundation.dart'
show
clampDouble
;
import
'package:flutter/foundation.dart'
show
Brightness
,
clampDouble
;
import
'package:flutter/rendering.dart'
;
import
'package:flutter/rendering.dart'
;
import
'package:flutter/widgets.dart'
;
import
'package:flutter/widgets.dart'
;
import
'colors.dart'
;
import
'text_selection_toolbar_button.dart'
;
import
'text_selection_toolbar_button.dart'
;
import
'theme.dart'
;
// Values extracted from https://developer.apple.com/design/resources/.
// Values extracted from https://developer.apple.com/design/resources/.
// The height of the toolbar, including the arrow.
// The height of the toolbar, including the arrow.
...
@@ -29,9 +31,27 @@ const double _kArrowScreenPadding = 26.0;
...
@@ -29,9 +31,27 @@ const double _kArrowScreenPadding = 26.0;
// Values extracted from https://developer.apple.com/design/resources/.
// Values extracted from https://developer.apple.com/design/resources/.
const
Radius
_kToolbarBorderRadius
=
Radius
.
circular
(
8
);
const
Radius
_kToolbarBorderRadius
=
Radius
.
circular
(
8
);
// Colors extracted from https://developer.apple.com/design/resources/.
const
CupertinoDynamicColor
_kToolbarDividerColor
=
CupertinoDynamicColor
.
withBrightness
(
// TODO(LongCatIsLooong): https://github.com/flutter/flutter/issues/41507.
// This value was extracted from a screenshot of iOS 16.0.3, as light mode
const
Color
_kToolbarDividerColor
=
Color
(
0xFF808080
);
// didn't appear in the Apple design resources assets linked below.
color:
Color
(
0xFFB6B6B6
),
// Color extracted from https://developer.apple.com/design/resources/.
// TODO(LongCatIsLooong): https://github.com/flutter/flutter/issues/41507.
darkColor:
Color
(
0xFF808080
),
);
// These values were extracted from a screenshot of iOS 16.0.3, as light mode
// didn't appear in the Apple design resources assets linked above.
final
BoxDecoration
_kToolbarShadow
=
BoxDecoration
(
borderRadius:
const
BorderRadius
.
all
(
_kToolbarBorderRadius
),
boxShadow:
<
BoxShadow
>[
BoxShadow
(
color:
CupertinoColors
.
black
.
withOpacity
(
0.1
),
blurRadius:
16.0
,
offset:
Offset
(
0
,
_kToolbarArrowSize
.
height
/
2
),
),
],
);
/// The type for a Function that builds a toolbar's container with the given
/// The type for a Function that builds a toolbar's container with the given
/// child.
/// child.
...
@@ -119,14 +139,23 @@ class CupertinoTextSelectionToolbar extends StatelessWidget {
...
@@ -119,14 +139,23 @@ class CupertinoTextSelectionToolbar extends StatelessWidget {
// Builds a toolbar just like the default iOS toolbar, with the right color
// Builds a toolbar just like the default iOS toolbar, with the right color
// background and a rounded cutout with an arrow.
// background and a rounded cutout with an arrow.
static
Widget
_defaultToolbarBuilder
(
BuildContext
context
,
Offset
anchor
,
bool
isAbove
,
Widget
child
)
{
static
Widget
_defaultToolbarBuilder
(
BuildContext
context
,
Offset
anchor
,
bool
isAbove
,
Widget
child
)
{
return
_CupertinoTextSelectionToolbarShape
(
final
Widget
outputChild
=
_CupertinoTextSelectionToolbarShape
(
anchor:
anchor
,
anchor:
anchor
,
isAbove:
isAbove
,
isAbove:
isAbove
,
child:
DecoratedBox
(
child:
DecoratedBox
(
decoration:
const
BoxDecoration
(
color:
_kToolbarDividerColor
),
decoration:
BoxDecoration
(
color:
_kToolbarDividerColor
.
resolveFrom
(
context
),
),
child:
child
,
child:
child
,
),
),
);
);
if
(
CupertinoTheme
.
brightnessOf
(
context
)
==
Brightness
.
dark
)
{
return
outputChild
;
}
return
DecoratedBox
(
decoration:
_kToolbarShadow
,
child:
outputChild
,
);
}
}
@override
@override
...
@@ -226,7 +255,6 @@ class _RenderCupertinoTextSelectionToolbarShape extends RenderShiftedBox {
...
@@ -226,7 +255,6 @@ class _RenderCupertinoTextSelectionToolbarShape extends RenderShiftedBox {
super
.
child
,
super
.
child
,
);
);
@override
@override
bool
get
isRepaintBoundary
=>
true
;
bool
get
isRepaintBoundary
=>
true
;
...
@@ -485,7 +513,7 @@ class _CupertinoTextSelectionToolbarContentState extends State<_CupertinoTextSel
...
@@ -485,7 +513,7 @@ class _CupertinoTextSelectionToolbarContentState extends State<_CupertinoTextSel
onPressed:
_handleNextPage
,
onPressed:
_handleNextPage
,
text:
'▶'
,
text:
'▶'
,
),
),
nextButtonDisabled:
CupertinoTextSelectionToolbarButton
.
text
(
nextButtonDisabled:
const
CupertinoTextSelectionToolbarButton
.
text
(
text:
'▶'
,
text:
'▶'
,
),
),
children:
widget
.
children
,
children:
widget
.
children
,
...
...
packages/flutter/lib/src/cupertino/text_selection_toolbar_button.dart
View file @
6781576e
...
@@ -18,7 +18,17 @@ const TextStyle _kToolbarButtonFontStyle = TextStyle(
...
@@ -18,7 +18,17 @@ const TextStyle _kToolbarButtonFontStyle = TextStyle(
// Colors extracted from https://developer.apple.com/design/resources/.
// Colors extracted from https://developer.apple.com/design/resources/.
// TODO(LongCatIsLooong): https://github.com/flutter/flutter/issues/41507.
// TODO(LongCatIsLooong): https://github.com/flutter/flutter/issues/41507.
const
Color
_kToolbarBackgroundColor
=
Color
(
0xEB202020
);
const
CupertinoDynamicColor
_kToolbarBackgroundColor
=
CupertinoDynamicColor
.
withBrightness
(
// This value was extracted from a screenshot of iOS 16.0.3, as light mode
// didn't appear in the Apple design resources assets linked above.
color:
Color
(
0xEBF7F7F7
),
darkColor:
Color
(
0xEB202020
),
);
const
CupertinoDynamicColor
_kToolbarTextColor
=
CupertinoDynamicColor
.
withBrightness
(
color:
CupertinoColors
.
black
,
darkColor:
CupertinoColors
.
white
,
);
// Eyeballed value.
// Eyeballed value.
const
EdgeInsets
_kToolbarButtonPadding
=
EdgeInsets
.
symmetric
(
vertical:
16.0
,
horizontal:
18.0
);
const
EdgeInsets
_kToolbarButtonPadding
=
EdgeInsets
.
symmetric
(
vertical:
16.0
,
horizontal:
18.0
);
...
@@ -33,22 +43,17 @@ class CupertinoTextSelectionToolbarButton extends StatelessWidget {
...
@@ -33,22 +43,17 @@ class CupertinoTextSelectionToolbarButton extends StatelessWidget {
this
.
onPressed
,
this
.
onPressed
,
required
Widget
this
.
child
,
required
Widget
this
.
child
,
})
:
assert
(
child
!=
null
),
})
:
assert
(
child
!=
null
),
text
=
null
,
buttonItem
=
null
;
buttonItem
=
null
;
/// Create an instance of [CupertinoTextSelectionToolbarButton] whose child is
/// Create an instance of [CupertinoTextSelectionToolbarButton] whose child is
/// a [Text] widget styled like the default iOS text selection toolbar button.
/// a [Text] widget styled like the default iOS text selection toolbar button.
CupertinoTextSelectionToolbarButton
.
text
({
const
CupertinoTextSelectionToolbarButton
.
text
({
super
.
key
,
super
.
key
,
this
.
onPressed
,
this
.
onPressed
,
required
String
text
,
required
this
.
text
,
})
:
buttonItem
=
null
,
})
:
buttonItem
=
null
,
child
=
Text
(
child
=
null
;
text
,
overflow:
TextOverflow
.
ellipsis
,
style:
_kToolbarButtonFontStyle
.
copyWith
(
color:
onPressed
!=
null
?
CupertinoColors
.
white
:
CupertinoColors
.
inactiveGray
,
),
);
/// Create an instance of [CupertinoTextSelectionToolbarButton] from the given
/// Create an instance of [CupertinoTextSelectionToolbarButton] from the given
/// [ContextMenuButtonItem].
/// [ContextMenuButtonItem].
...
@@ -59,6 +64,7 @@ class CupertinoTextSelectionToolbarButton extends StatelessWidget {
...
@@ -59,6 +64,7 @@ class CupertinoTextSelectionToolbarButton extends StatelessWidget {
required
ContextMenuButtonItem
this
.
buttonItem
,
required
ContextMenuButtonItem
this
.
buttonItem
,
})
:
assert
(
buttonItem
!=
null
),
})
:
assert
(
buttonItem
!=
null
),
child
=
null
,
child
=
null
,
text
=
null
,
onPressed
=
buttonItem
.
onPressed
;
onPressed
=
buttonItem
.
onPressed
;
/// {@template flutter.cupertino.CupertinoTextSelectionToolbarButton.child}
/// {@template flutter.cupertino.CupertinoTextSelectionToolbarButton.child}
...
@@ -79,6 +85,10 @@ class CupertinoTextSelectionToolbarButton extends StatelessWidget {
...
@@ -79,6 +85,10 @@ class CupertinoTextSelectionToolbarButton extends StatelessWidget {
/// {@endtemplate}
/// {@endtemplate}
final
ContextMenuButtonItem
?
buttonItem
;
final
ContextMenuButtonItem
?
buttonItem
;
/// The text used in the button's label when using
/// [CupertinoTextSelectionToolbarButton.text].
final
String
?
text
;
/// Returns the default button label String for the button of the given
/// Returns the default button label String for the button of the given
/// [ContextMenuButtonItem]'s [ContextMenuButtonType].
/// [ContextMenuButtonItem]'s [ContextMenuButtonType].
static
String
getButtonLabel
(
BuildContext
context
,
ContextMenuButtonItem
buttonItem
)
{
static
String
getButtonLabel
(
BuildContext
context
,
ContextMenuButtonItem
buttonItem
)
{
...
@@ -106,12 +116,15 @@ class CupertinoTextSelectionToolbarButton extends StatelessWidget {
...
@@ -106,12 +116,15 @@ class CupertinoTextSelectionToolbarButton extends StatelessWidget {
@override
@override
Widget
build
(
BuildContext
context
)
{
Widget
build
(
BuildContext
context
)
{
final
Widget
child
=
this
.
child
??
Text
(
final
Widget
child
=
this
.
child
??
Text
(
getButtonLabel
(
context
,
buttonItem
!),
text
??
getButtonLabel
(
context
,
buttonItem
!),
overflow:
TextOverflow
.
ellipsis
,
overflow:
TextOverflow
.
ellipsis
,
style:
_kToolbarButtonFontStyle
.
copyWith
(
style:
_kToolbarButtonFontStyle
.
copyWith
(
color:
onPressed
!=
null
?
CupertinoColors
.
white
:
CupertinoColors
.
inactiveGray
,
color:
onPressed
!=
null
),
?
_kToolbarTextColor
.
resolveFrom
(
context
)
);
:
CupertinoColors
.
inactiveGray
,
),
);
return
CupertinoButton
(
return
CupertinoButton
(
borderRadius:
null
,
borderRadius:
null
,
color:
_kToolbarBackgroundColor
,
color:
_kToolbarBackgroundColor
,
...
...
packages/flutter/test/cupertino/text_field_test.dart
View file @
6781576e
...
@@ -1500,7 +1500,7 @@ void main() {
...
@@ -1500,7 +1500,7 @@ void main() {
expect
(
controller
.
text
,
'abcdef'
);
expect
(
controller
.
text
,
'abcdef'
);
});
});
testWidgets
(
'toolbar
has the same visual regardless of theming
'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'toolbar
colors change with theme brightness, but nothing else
'
,
(
WidgetTester
tester
)
async
{
final
TextEditingController
controller
=
TextEditingController
(
final
TextEditingController
controller
=
TextEditingController
(
text:
"j'aime la poutine"
,
text:
"j'aime la poutine"
,
);
);
...
@@ -1524,7 +1524,7 @@ void main() {
...
@@ -1524,7 +1524,7 @@ void main() {
await
tester
.
pump
(
const
Duration
(
milliseconds:
200
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
200
));
Text
text
=
tester
.
widget
<
Text
>(
find
.
text
(
'Paste'
));
Text
text
=
tester
.
widget
<
Text
>(
find
.
text
(
'Paste'
));
expect
(
text
.
style
!.
color
,
CupertinoColors
.
whit
e
);
expect
(
text
.
style
!.
color
!.
value
,
CupertinoColors
.
black
.
valu
e
);
expect
(
text
.
style
!.
fontSize
,
14
);
expect
(
text
.
style
!.
fontSize
,
14
);
expect
(
text
.
style
!.
letterSpacing
,
-
0.15
);
expect
(
text
.
style
!.
letterSpacing
,
-
0.15
);
expect
(
text
.
style
!.
fontWeight
,
FontWeight
.
w400
);
expect
(
text
.
style
!.
fontWeight
,
FontWeight
.
w400
);
...
@@ -1556,7 +1556,7 @@ void main() {
...
@@ -1556,7 +1556,7 @@ void main() {
text
=
tester
.
widget
<
Text
>(
find
.
text
(
'Paste'
));
text
=
tester
.
widget
<
Text
>(
find
.
text
(
'Paste'
));
// The toolbar buttons' text are still the same style.
// The toolbar buttons' text are still the same style.
expect
(
text
.
style
!.
color
,
CupertinoColors
.
whit
e
);
expect
(
text
.
style
!.
color
!.
value
,
CupertinoColors
.
white
.
valu
e
);
expect
(
text
.
style
!.
fontSize
,
14
);
expect
(
text
.
style
!.
fontSize
,
14
);
expect
(
text
.
style
!.
letterSpacing
,
-
0.15
);
expect
(
text
.
style
!.
letterSpacing
,
-
0.15
);
expect
(
text
.
style
!.
fontWeight
,
FontWeight
.
w400
);
expect
(
text
.
style
!.
fontWeight
,
FontWeight
.
w400
);
...
...
packages/flutter/test/cupertino/text_selection_toolbar_test.dart
View file @
6781576e
...
@@ -60,6 +60,11 @@ class TestBox extends SizedBox {
...
@@ -60,6 +60,11 @@ class TestBox extends SizedBox {
static
const
double
itemWidth
=
100.0
;
static
const
double
itemWidth
=
100.0
;
}
}
const
CupertinoDynamicColor
_kToolbarBackgroundColor
=
CupertinoDynamicColor
.
withBrightness
(
color:
Color
(
0xEBF7F7F7
),
darkColor:
Color
(
0xEB202020
),
);
void
main
(
)
{
void
main
(
)
{
TestWidgetsFlutterBinding
.
ensureInitialized
();
TestWidgetsFlutterBinding
.
ensureInitialized
();
...
@@ -289,4 +294,64 @@ void main() {
...
@@ -289,4 +294,64 @@ void main() {
expect
(
find
.
text
(
'Paste'
),
findsNothing
);
expect
(
find
.
text
(
'Paste'
),
findsNothing
);
expect
(
find
.
text
(
'Select all'
),
findsNothing
);
expect
(
find
.
text
(
'Select all'
),
findsNothing
);
},
skip:
kIsWeb
);
// [intended] We do not use Flutter-rendered context menu on the Web.
},
skip:
kIsWeb
);
// [intended] We do not use Flutter-rendered context menu on the Web.
for
(
final
Brightness
?
themeBrightness
in
<
Brightness
?>[...
Brightness
.
values
,
null
])
{
for
(
final
Brightness
?
mediaBrightness
in
<
Brightness
?>[...
Brightness
.
values
,
null
])
{
testWidgets
(
'draws dark buttons in dark mode and light button in light mode when theme is
$themeBrightness
and MediaQuery is
$mediaBrightness
'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
CupertinoApp
(
theme:
CupertinoThemeData
(
brightness:
themeBrightness
,
),
home:
Center
(
child:
Builder
(
builder:
(
BuildContext
context
)
{
return
MediaQuery
(
data:
MediaQuery
.
of
(
context
).
copyWith
(
platformBrightness:
mediaBrightness
),
child:
CupertinoTextSelectionToolbar
(
anchorAbove:
const
Offset
(
100.0
,
0.0
),
anchorBelow:
const
Offset
(
100.0
,
0.0
),
children:
<
Widget
>[
CupertinoTextSelectionToolbarButton
.
text
(
onPressed:
()
{},
text:
'Button'
,
),
],
),
);
},
),
),
),
);
final
Finder
buttonFinder
=
find
.
byType
(
CupertinoButton
);
expect
(
buttonFinder
,
findsOneWidget
);
final
Finder
decorationFinder
=
find
.
descendant
(
of:
find
.
byType
(
CupertinoButton
),
matching:
find
.
byType
(
DecoratedBox
)
);
expect
(
decorationFinder
,
findsOneWidget
);
final
DecoratedBox
decoratedBox
=
tester
.
widget
(
decorationFinder
);
final
BoxDecoration
boxDecoration
=
decoratedBox
.
decoration
as
BoxDecoration
;
// Theme brightness is preferred, otherwise MediaQuery brightness is
// used. If both are null, defaults to light.
late
final
Brightness
effectiveBrightness
;
if
(
themeBrightness
!=
null
)
{
effectiveBrightness
=
themeBrightness
;
}
else
{
effectiveBrightness
=
mediaBrightness
??
Brightness
.
light
;
}
expect
(
boxDecoration
.
color
!.
value
,
effectiveBrightness
==
Brightness
.
dark
?
_kToolbarBackgroundColor
.
darkColor
.
value
:
_kToolbarBackgroundColor
.
color
.
value
,
);
},
skip:
kIsWeb
);
// [intended] We do not use Flutter-rendered context menu on the Web.
}
}
}
}
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