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
27896a7b
Unverified
Commit
27896a7b
authored
Sep 06, 2022
by
Valentin Vignal
Committed by
GitHub
Sep 06, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Adds `PopupMenuPosition position` to the `PopupMenuThemeData` (#110268)
parent
22cef489
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
86 additions
and
38 deletions
+86
-38
popup_menu.dart
packages/flutter/lib/src/material/popup_menu.dart
+8
-13
popup_menu_theme.dart
packages/flutter/lib/src/material/popup_menu_theme.dart
+22
-1
popup_menu_theme_test.dart
packages/flutter/test/material/popup_menu_theme_test.dart
+56
-24
No files found.
packages/flutter/lib/src/material/popup_menu.dart
View file @
27896a7b
...
...
@@ -38,14 +38,6 @@ const double _kMenuVerticalPadding = 8.0;
const
double
_kMenuWidthStep
=
56.0
;
const
double
_kMenuScreenPadding
=
8.0
;
/// Used to configure how the [PopupMenuButton] positions its popup menu.
enum
PopupMenuPosition
{
/// Menu is positioned over the anchor.
over
,
/// Menu is positioned under the anchor.
under
,
}
/// A base class for entries in a Material Design popup menu.
///
/// The popup menu widget uses this interface to interact with the menu items.
...
...
@@ -1025,7 +1017,7 @@ class PopupMenuButton<T> extends StatefulWidget {
this
.
color
,
this
.
enableFeedback
,
this
.
constraints
,
this
.
position
=
PopupMenuPosition
.
over
,
this
.
position
,
this
.
clipBehavior
=
Clip
.
none
,
})
:
assert
(
itemBuilder
!=
null
),
assert
(
enabled
!=
null
),
...
...
@@ -1157,9 +1149,11 @@ class PopupMenuButton<T> extends StatefulWidget {
/// [offset] is used to change the position of the popup menu relative to the
/// position set by this parameter.
///
/// When not set, the position defaults to [PopupMenuPosition.over] which makes the
/// popup menu appear directly over the button that was used to create it.
final
PopupMenuPosition
position
;
/// If this property is `null`, then [PopupMenuThemeData.position] is used. If
/// [PopupMenuThemeData.position] is also `null`, then the position defaults
/// to [PopupMenuPosition.over] which makes the popup menu appear directly
/// over the button that was used to create it.
final
PopupMenuPosition
?
position
;
/// {@macro flutter.material.Material.clipBehavior}
///
...
...
@@ -1189,8 +1183,9 @@ class PopupMenuButtonState<T> extends State<PopupMenuButton<T>> {
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
PopupMenuPosition
popupMenuPosition
=
widget
.
position
??
popupMenuTheme
.
position
??
PopupMenuPosition
.
over
;
final
Offset
offset
;
switch
(
widget
.
p
osition
)
{
switch
(
popupMenuP
osition
)
{
case
PopupMenuPosition
.
over
:
offset
=
widget
.
offset
;
break
;
...
...
packages/flutter/lib/src/material/popup_menu_theme.dart
View file @
27896a7b
...
...
@@ -13,6 +13,14 @@ import 'theme.dart';
// Examples can assume:
// late BuildContext context;
/// Used to configure how the [PopupMenuButton] positions its popup menu.
enum
PopupMenuPosition
{
/// Menu is positioned over the anchor.
over
,
/// Menu is positioned under the anchor.
under
,
}
/// Defines the visual properties of the routes used to display popup menus
/// as well as [PopupMenuItem] and [PopupMenuDivider] widgets.
///
...
...
@@ -43,6 +51,7 @@ class PopupMenuThemeData with Diagnosticable {
this
.
textStyle
,
this
.
enableFeedback
,
this
.
mouseCursor
,
this
.
position
,
});
/// The background color of the popup menu.
...
...
@@ -67,6 +76,12 @@ class PopupMenuThemeData with Diagnosticable {
/// If specified, overrides the default value of [PopupMenuItem.mouseCursor].
final
MaterialStateProperty
<
MouseCursor
?>?
mouseCursor
;
/// Whether the popup menu is positioned over or under the popup menu button.
///
/// When not set, the position defaults to [PopupMenuPosition.over] which makes the
/// popup menu appear directly over the button that was used to create it.
final
PopupMenuPosition
?
position
;
/// Creates a copy of this object with the given fields replaced with the
/// new values.
PopupMenuThemeData
copyWith
({
...
...
@@ -76,6 +91,7 @@ class PopupMenuThemeData with Diagnosticable {
TextStyle
?
textStyle
,
bool
?
enableFeedback
,
MaterialStateProperty
<
MouseCursor
?>?
mouseCursor
,
PopupMenuPosition
?
position
,
})
{
return
PopupMenuThemeData
(
color:
color
??
this
.
color
,
...
...
@@ -84,6 +100,7 @@ class PopupMenuThemeData with Diagnosticable {
textStyle:
textStyle
??
this
.
textStyle
,
enableFeedback:
enableFeedback
??
this
.
enableFeedback
,
mouseCursor:
mouseCursor
??
this
.
mouseCursor
,
position:
position
??
this
.
position
,
);
}
...
...
@@ -104,6 +121,7 @@ class PopupMenuThemeData with Diagnosticable {
textStyle:
TextStyle
.
lerp
(
a
?.
textStyle
,
b
?.
textStyle
,
t
),
enableFeedback:
t
<
0.5
?
a
?.
enableFeedback
:
b
?.
enableFeedback
,
mouseCursor:
t
<
0.5
?
a
?.
mouseCursor
:
b
?.
mouseCursor
,
position:
t
<
0.5
?
a
?.
position
:
b
?.
position
,
);
}
...
...
@@ -115,6 +133,7 @@ class PopupMenuThemeData with Diagnosticable {
textStyle
,
enableFeedback
,
mouseCursor
,
position
,
);
@override
...
...
@@ -131,7 +150,8 @@ class PopupMenuThemeData with Diagnosticable {
&&
other
.
shape
==
shape
&&
other
.
textStyle
==
textStyle
&&
other
.
enableFeedback
==
enableFeedback
&&
other
.
mouseCursor
==
mouseCursor
;
&&
other
.
mouseCursor
==
mouseCursor
&&
other
.
position
==
position
;
}
@override
...
...
@@ -143,6 +163,7 @@ class PopupMenuThemeData with Diagnosticable {
properties
.
add
(
DiagnosticsProperty
<
TextStyle
>(
'text style'
,
textStyle
,
defaultValue:
null
));
properties
.
add
(
DiagnosticsProperty
<
bool
>(
'enableFeedback'
,
enableFeedback
,
defaultValue:
null
));
properties
.
add
(
DiagnosticsProperty
<
MaterialStateProperty
<
MouseCursor
?>>(
'mouseCursor'
,
mouseCursor
,
defaultValue:
null
));
properties
.
add
(
EnumProperty
<
PopupMenuPosition
?>(
'position'
,
position
,
defaultValue:
null
));
}
}
...
...
packages/flutter/test/material/popup_menu_theme_test.dart
View file @
27896a7b
...
...
@@ -13,6 +13,7 @@ PopupMenuThemeData _popupMenuTheme() {
shape:
BeveledRectangleBorder
(
borderRadius:
BorderRadius
.
all
(
Radius
.
circular
(
12
))),
elevation:
12.0
,
textStyle:
TextStyle
(
color:
Color
(
0xffffffff
),
textBaseline:
TextBaseline
.
alphabetic
),
position:
PopupMenuPosition
.
under
,
);
}
...
...
@@ -29,6 +30,7 @@ void main() {
expect
(
popupMenuTheme
.
elevation
,
null
);
expect
(
popupMenuTheme
.
textStyle
,
null
);
expect
(
popupMenuTheme
.
mouseCursor
,
null
);
expect
(
popupMenuTheme
.
position
,
null
);
});
testWidgets
(
'Default PopupMenuThemeData debugFillProperties'
,
(
WidgetTester
tester
)
async
{
...
...
@@ -51,6 +53,7 @@ void main() {
elevation:
2.0
,
textStyle:
TextStyle
(
color:
Color
(
0xffffffff
)),
mouseCursor:
MaterialStateMouseCursor
.
clickable
,
position:
PopupMenuPosition
.
over
,
).
debugFillProperties
(
builder
);
final
List
<
String
>
description
=
builder
.
properties
...
...
@@ -64,6 +67,7 @@ void main() {
'elevation: 2.0'
,
'text style: TextStyle(inherit: true, color: Color(0xffffffff))'
,
'mouseCursor: MaterialStateMouseCursor(clickable)'
,
'position: over'
]);
});
...
...
@@ -78,16 +82,21 @@ void main() {
home:
Material
(
child:
Column
(
children:
<
Widget
>[
PopupMenuButton
<
void
>(
key:
popupButtonKey
,
itemBuilder:
(
BuildContext
context
)
{
return
<
PopupMenuEntry
<
void
>>[
PopupMenuItem
<
void
>(
key:
popupItemKey
,
child:
const
Text
(
'Example'
),
),
];
},
Padding
(
// The padding makes sure the menu as enough space to around to
// get properly aligned when displayed (`_kMenuScreenPadding`).
padding:
const
EdgeInsets
.
all
(
8.0
),
child:
PopupMenuButton
<
void
>(
key:
popupButtonKey
,
itemBuilder:
(
BuildContext
context
)
{
return
<
PopupMenuEntry
<
void
>>[
PopupMenuItem
<
void
>(
key:
popupItemKey
,
child:
const
Text
(
'Example'
),
),
];
},
),
),
],
),
...
...
@@ -123,6 +132,11 @@ void main() {
);
expect
(
text
.
style
.
fontFamily
,
'Roboto'
);
expect
(
text
.
style
.
color
,
const
Color
(
0xdd000000
));
expect
(
text
.
style
.
color
,
const
Color
(
0xdd000000
));
final
Offset
topLeftButton
=
tester
.
getTopLeft
(
find
.
byType
(
PopupMenuButton
<
void
>));
final
Offset
topLeftMenu
=
tester
.
getTopLeft
(
find
.
byWidget
(
button
));
expect
(
topLeftMenu
,
topLeftButton
);
});
testWidgets
(
'Popup menu uses values from PopupMenuThemeData'
,
(
WidgetTester
tester
)
async
{
...
...
@@ -138,6 +152,10 @@ void main() {
child:
Column
(
children:
<
Widget
>[
PopupMenuButton
<
void
>(
// The padding is used in the positioning of the menu when the
// position is `PopupMenuPosition.under`. Setting it to zero makes
// it easier to test.
padding:
EdgeInsets
.
zero
,
key:
popupButtonKey
,
itemBuilder:
(
BuildContext
context
)
{
return
<
PopupMenuEntry
<
Object
>>[
...
...
@@ -181,6 +199,10 @@ void main() {
).
last
,
);
expect
(
text
.
style
,
popupMenuTheme
.
textStyle
);
final
Offset
bottomLeftButton
=
tester
.
getBottomLeft
(
find
.
byType
(
PopupMenuButton
<
void
>));
final
Offset
topLeftMenu
=
tester
.
getTopLeft
(
find
.
byWidget
(
button
));
expect
(
topLeftMenu
,
bottomLeftButton
);
});
testWidgets
(
'Popup menu widget properties take priority over theme'
,
(
WidgetTester
tester
)
async
{
...
...
@@ -202,20 +224,26 @@ void main() {
home:
Material
(
child:
Column
(
children:
<
Widget
>[
PopupMenuButton
<
void
>(
key:
popupButtonKey
,
elevation:
elevation
,
color:
color
,
shape:
shape
,
itemBuilder:
(
BuildContext
context
)
{
return
<
PopupMenuEntry
<
void
>>[
PopupMenuItem
<
void
>(
key:
popupItemKey
,
textStyle:
textStyle
,
child:
const
Text
(
'Example'
),
),
];
},
Padding
(
// The padding makes sure the menu as enough space to around to
// get properly aligned when displayed (`_kMenuScreenPadding`).
padding:
const
EdgeInsets
.
all
(
8.0
),
child:
PopupMenuButton
<
void
>(
key:
popupButtonKey
,
elevation:
elevation
,
color:
color
,
shape:
shape
,
position:
PopupMenuPosition
.
over
,
itemBuilder:
(
BuildContext
context
)
{
return
<
PopupMenuEntry
<
void
>>[
PopupMenuItem
<
void
>(
key:
popupItemKey
,
textStyle:
textStyle
,
child:
const
Text
(
'Example'
),
),
];
},
),
),
],
),
...
...
@@ -250,6 +278,10 @@ void main() {
).
last
,
);
expect
(
text
.
style
,
textStyle
);
final
Offset
topLeftButton
=
tester
.
getTopLeft
(
find
.
byType
(
PopupMenuButton
<
void
>));
final
Offset
topLeftMenu
=
tester
.
getTopLeft
(
find
.
byWidget
(
button
));
expect
(
topLeftMenu
,
topLeftButton
);
});
testWidgets
(
'ThemeData.popupMenuTheme properties are utilized'
,
(
WidgetTester
tester
)
async
{
...
...
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