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
fe57037a
Unverified
Commit
fe57037a
authored
Apr 21, 2021
by
Shi-Hao Hong
Committed by
GitHub
Apr 21, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Revert "Update PopupMenuButton widget (#80420)" (#80831)
parent
61c30c41
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
13 additions
and
150 deletions
+13
-150
popup_menu.dart
packages/flutter/lib/src/material/popup_menu.dart
+13
-69
popup_menu_test.dart
packages/flutter/test/material/popup_menu_test.dart
+0
-81
No files found.
packages/flutter/lib/src/material/popup_menu.dart
View file @
fe57037a
...
...
@@ -732,8 +732,6 @@ class _PopupMenuRoute<T> extends PopupRoute<T> {
this
.
shape
,
this
.
color
,
required
this
.
capturedThemes
,
this
.
menuKey
,
this
.
positionCallback
,
})
:
itemSizes
=
List
<
Size
?>.
filled
(
items
.
length
,
null
);
final
RelativeRect
position
;
...
...
@@ -745,8 +743,6 @@ class _PopupMenuRoute<T> extends PopupRoute<T> {
final
ShapeBorder
?
shape
;
final
Color
?
color
;
final
CapturedThemes
capturedThemes
;
final
Key
?
menuKey
;
final
PopupMenuButtonPositionCallback
?
positionCallback
;
@override
Animation
<
double
>
createAnimation
()
{
...
...
@@ -782,13 +778,12 @@ class _PopupMenuRoute<T> extends PopupRoute<T> {
final
Widget
menu
=
_PopupMenu
<
T
>(
route:
this
,
semanticLabel:
semanticLabel
);
return
StatefulBuilder
(
key:
menuKey
,
builder:
(
BuildContext
context
,
StateSetter
setState
)
{
return
Builder
(
builder:
(
BuildContext
context
)
{
final
MediaQueryData
mediaQuery
=
MediaQuery
.
of
(
context
);
return
CustomSingleChildLayout
(
delegate:
_PopupMenuRouteLayout
(
position
Callback
==
null
?
position
:
positionCallback
!()
,
position
,
itemSizes
,
selectedItemIndex
,
Directionality
.
of
(
context
),
...
...
@@ -806,10 +801,6 @@ class _PopupMenuRoute<T> extends PopupRoute<T> {
///
/// `items` should be non-null and not empty.
///
/// Prefer to use `positionCallback` to obtain position instead of 'position'
/// when `positionCallback` is non-null. In this way, the position of the menu
/// can be recalculated through this callback during the rebuild phase of the menu.
///
/// If `initialValue` is specified then the first item with a matching value
/// will be highlighted and the value of `position` gives the rectangle whose
/// vertical center will be aligned with the vertical center of the highlighted
...
...
@@ -871,8 +862,6 @@ Future<T?> showMenu<T>({
ShapeBorder
?
shape
,
Color
?
color
,
bool
useRootNavigator
=
false
,
Key
?
menuKey
,
PopupMenuButtonPositionCallback
?
positionCallback
,
})
{
assert
(
context
!=
null
);
assert
(
position
!=
null
);
...
...
@@ -902,8 +891,6 @@ Future<T?> showMenu<T>({
shape:
shape
,
color:
color
,
capturedThemes:
InheritedTheme
.
capture
(
from:
context
,
to:
navigator
.
context
),
menuKey:
menuKey
,
positionCallback:
positionCallback
,
));
}
...
...
@@ -1103,44 +1090,11 @@ class PopupMenuButton<T> extends StatefulWidget {
PopupMenuButtonState
<
T
>
createState
()
=>
PopupMenuButtonState
<
T
>();
}
/// Signature for the callback used by [showMenu] to obtain the position of the
/// [PopupMenuButton].
///
/// Used by [showMenu].
typedef
PopupMenuButtonPositionCallback
=
RelativeRect
Function
();
/// The [State] for a [PopupMenuButton].
///
/// See [showButtonMenu] for a way to programmatically open the popup menu
/// of your button state.
class
PopupMenuButtonState
<
T
>
extends
State
<
PopupMenuButton
<
T
>>
{
GlobalKey
_menuGlobalKey
=
GlobalKey
();
RelativeRect
?
_buttonPosition
;
RelativeRect
_getButtonPosition
()
=>
_buttonPosition
!;
RelativeRect
_calculateButtonPosition
()
{
final
RenderBox
button
=
context
.
findRenderObject
()!
as
RenderBox
;
final
RenderBox
overlay
=
Navigator
.
of
(
context
).
overlay
!.
context
.
findRenderObject
()!
as
RenderBox
;
return
RelativeRect
.
fromRect
(
Rect
.
fromPoints
(
button
.
localToGlobal
(
widget
.
offset
,
ancestor:
overlay
),
button
.
localToGlobal
(
button
.
size
.
bottomRight
(
Offset
.
zero
)
+
widget
.
offset
,
ancestor:
overlay
),
),
Offset
.
zero
&
overlay
.
size
,
);
}
void
_maybeUpdateMenuPosition
()
{
WidgetsBinding
.
instance
!.
addPostFrameCallback
((
Duration
duration
)
{
final
RelativeRect
newPosition
=
_calculateButtonPosition
();
if
(
newPosition
!=
_buttonPosition
)
{
_menuGlobalKey
.
currentState
?.
setState
(()
{});
_buttonPosition
=
newPosition
;
}
});
}
/// A method to show a popup menu with the items supplied to
/// [PopupMenuButton.itemBuilder] at the position of your [PopupMenuButton].
///
...
...
@@ -1151,12 +1105,16 @@ class PopupMenuButtonState<T> extends State<PopupMenuButton<T>> {
/// show the menu of the button with `globalKey.currentState.showButtonMenu`.
void
showButtonMenu
()
{
final
PopupMenuThemeData
popupMenuTheme
=
PopupMenuTheme
.
of
(
context
);
final
RenderBox
button
=
context
.
findRenderObject
()!
as
RenderBox
;
final
RenderBox
overlay
=
Navigator
.
of
(
context
).
overlay
!.
context
.
findRenderObject
()!
as
RenderBox
;
final
RelativeRect
position
=
RelativeRect
.
fromRect
(
Rect
.
fromPoints
(
button
.
localToGlobal
(
widget
.
offset
,
ancestor:
overlay
),
button
.
localToGlobal
(
button
.
size
.
bottomRight
(
Offset
.
zero
)
+
widget
.
offset
,
ancestor:
overlay
),
),
Offset
.
zero
&
overlay
.
size
,
);
final
List
<
PopupMenuEntry
<
T
>>
items
=
widget
.
itemBuilder
(
context
);
// It is possible that the fade-out animation of the menu has not finished
// yet, and the key needs to be regenerated at this time, otherwise there will
// be an exception of duplicate GlobalKey.
if
(
_menuGlobalKey
.
currentState
!=
null
)
_menuGlobalKey
=
GlobalKey
();
// Only show the menu if there is something to show
if
(
items
.
isNotEmpty
)
{
showMenu
<
T
?>(
...
...
@@ -1164,11 +1122,9 @@ class PopupMenuButtonState<T> extends State<PopupMenuButton<T>> {
elevation:
widget
.
elevation
??
popupMenuTheme
.
elevation
,
items:
items
,
initialValue:
widget
.
initialValue
,
position:
_buttonPosition
!
,
position:
position
,
shape:
widget
.
shape
??
popupMenuTheme
.
shape
,
color:
widget
.
color
??
popupMenuTheme
.
color
,
menuKey:
_menuGlobalKey
,
positionCallback:
_getButtonPosition
,
)
.
then
<
void
>((
T
?
newValue
)
{
if
(!
mounted
)
...
...
@@ -1192,18 +1148,6 @@ class PopupMenuButtonState<T> extends State<PopupMenuButton<T>> {
}
}
@override
void
didUpdateWidget
(
PopupMenuButton
<
T
>
oldWidget
)
{
_maybeUpdateMenuPosition
();
super
.
didUpdateWidget
(
oldWidget
);
}
@override
void
didChangeDependencies
()
{
_maybeUpdateMenuPosition
();
super
.
didChangeDependencies
();
}
@override
Widget
build
(
BuildContext
context
)
{
final
bool
enableFeedback
=
widget
.
enableFeedback
...
...
packages/flutter/test/material/popup_menu_test.dart
View file @
fe57037a
...
...
@@ -2209,87 +2209,6 @@ void main() {
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'foo'
),
findsOneWidget
);
});
testWidgets
(
'The opened menu should follow if the button
\'
s position changed'
,
(
WidgetTester
tester
)
async
{
final
GlobalKey
buttonKey
=
GlobalKey
();
Widget
buildFrame
(
double
width
,
double
height
)
{
return
MaterialApp
(
home:
Scaffold
(
body:
SizedBox
(
height:
height
,
width:
width
,
child:
Center
(
child:
PopupMenuButton
<
int
>(
child:
SizedBox
(
key:
buttonKey
,
height:
10.0
,
width:
10.0
,
child:
const
ColoredBox
(
color:
Colors
.
pink
,
),
),
itemBuilder:
(
BuildContext
context
)
=>
<
PopupMenuEntry
<
int
>>[
const
PopupMenuItem
<
int
>(
child:
Text
(
'-1-'
),
value:
1
),
const
PopupMenuItem
<
int
>(
child:
Text
(
'-2-'
),
value:
2
),
],
),
),
),
),
);
}
await
tester
.
pumpWidget
(
buildFrame
(
100.0
,
100.0
));
// Open the menu.
await
tester
.
tap
(
find
.
byKey
(
buttonKey
));
await
tester
.
pumpAndSettle
();
// +--------+--------+ 100
// | | |
// | | (50,50)|
// +--------+--------+
// | | |
// | | |
// 100 +--------+--------+
//
// The button is a rectangle of 10 * 10 size and is centered,
// so its top-left offset should be (45.0, 45.0).
Offset
buttonOffset
=
tester
.
getTopLeft
(
find
.
byKey
(
buttonKey
));
expect
(
buttonOffset
,
const
Offset
(
45.0
,
45.0
));
// The top-left corner of the menu and button should be aligned.
Offset
popupMenuOffset
=
tester
.
getTopLeft
(
find
.
byType
(
SingleChildScrollView
));
expect
(
popupMenuOffset
,
buttonOffset
);
// Keep the menu opened and re-layout the screen.
await
tester
.
pumpWidget
(
buildFrame
(
200.0
,
300.0
));
// +-----------+-----------+ 200
// | | |
// | | |
// | | |
// | | |
// | | (100,150) |
// +-----------+-----------+
// | | |
// | | |
// | | |
// | | |
// | | |
// 300 +-----------+-----------+
//
// The button is a rectangle of 10 * 10 size and is centered,
// so its top-left offset should be (95.0, 145.0).
await
tester
.
pump
();
// Need a frame to update the menu.
buttonOffset
=
tester
.
getTopLeft
(
find
.
byKey
(
buttonKey
));
expect
(
buttonOffset
,
const
Offset
(
95.0
,
145.0
));
// The popup menu should follow the button.
popupMenuOffset
=
tester
.
getTopLeft
(
find
.
byType
(
SingleChildScrollView
));
expect
(
popupMenuOffset
,
buttonOffset
);
});
}
class
TestApp
extends
StatefulWidget
{
...
...
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