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
e352e086
Unverified
Commit
e352e086
authored
Mar 09, 2021
by
YeungKC
Committed by
GitHub
Mar 09, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add menuMaxHeight for DropdownButton (#76493)
parent
9300ad37
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
83 additions
and
3 deletions
+83
-3
dropdown.dart
packages/flutter/lib/src/material/dropdown.dart
+22
-1
dropdown_test.dart
packages/flutter/test/material/dropdown_test.dart
+61
-2
No files found.
packages/flutter/lib/src/material/dropdown.dart
View file @
e352e086
...
...
@@ -325,7 +325,10 @@ class _DropdownMenuRouteLayout<T> extends SingleChildLayoutDelegate {
// the view height. This ensures a tappable area outside of the simple menu
// with which to dismiss the menu.
// -- https://material.io/design/components/menus.html#usage
final
double
maxHeight
=
math
.
max
(
0.0
,
constraints
.
maxHeight
-
2
*
_kMenuItemHeight
);
double
maxHeight
=
math
.
max
(
0.0
,
constraints
.
maxHeight
-
2
*
_kMenuItemHeight
);
if
(
route
.
menuMaxHeight
!=
null
&&
route
.
menuMaxHeight
!
<=
maxHeight
)
{
maxHeight
=
route
.
menuMaxHeight
!;
}
// The width of a menu should be at most the view width. This ensures that
// the menu does not extend past the left and right edges of the screen.
final
double
width
=
math
.
min
(
constraints
.
maxWidth
,
buttonRect
.
width
);
...
...
@@ -411,6 +414,7 @@ class _DropdownRoute<T> extends PopupRoute<_DropdownRouteResult<T>> {
this
.
barrierLabel
,
this
.
itemHeight
,
this
.
dropdownColor
,
this
.
menuMaxHeight
,
})
:
assert
(
style
!=
null
),
itemHeights
=
List
<
double
>.
filled
(
items
.
length
,
itemHeight
??
kMinInteractiveDimension
);
...
...
@@ -423,6 +427,8 @@ class _DropdownRoute<T> extends PopupRoute<_DropdownRouteResult<T>> {
final
TextStyle
style
;
final
double
?
itemHeight
;
final
Color
?
dropdownColor
;
final
double
?
menuMaxHeight
;
final
List
<
double
>
itemHeights
;
ScrollController
?
scrollController
;
...
...
@@ -845,6 +851,7 @@ class DropdownButton<T> extends StatefulWidget {
this
.
focusNode
,
this
.
autofocus
=
false
,
this
.
dropdownColor
,
this
.
menuMaxHeight
,
// When adding new arguments, consider adding similar arguments to
// DropdownButtonFormField.
})
:
assert
(
items
==
null
||
items
.
isEmpty
||
value
==
null
||
...
...
@@ -1094,6 +1101,17 @@ class DropdownButton<T> extends StatefulWidget {
/// instead.
final
Color
?
dropdownColor
;
/// The maximum height of the menu.
///
/// The maximum height of the menu must be at least one row shorter than
/// the height of the app's view. This ensures that a tappable area
/// outside of the simple menu is present so the user can dismiss the menu.
///
/// If this property is set above the maximum allowable height threshold
/// mentioned above, then the menu defaults to being padded at the top
/// and bottom of the menu by at one menu item's height.
final
double
?
menuMaxHeight
;
@override
_DropdownButtonState
<
T
>
createState
()
=>
_DropdownButtonState
<
T
>();
}
...
...
@@ -1240,6 +1258,7 @@ class _DropdownButtonState<T> extends State<DropdownButton<T>> with WidgetsBindi
barrierLabel:
MaterialLocalizations
.
of
(
context
).
modalBarrierDismissLabel
,
itemHeight:
widget
.
itemHeight
,
dropdownColor:
widget
.
dropdownColor
,
menuMaxHeight:
widget
.
menuMaxHeight
,
);
navigator
.
push
(
_dropdownRoute
!).
then
<
void
>((
_DropdownRouteResult
<
T
>?
newValue
)
{
...
...
@@ -1488,6 +1507,7 @@ class DropdownButtonFormField<T> extends FormField<T> {
)
bool
autovalidate
=
false
,
AutovalidateMode
?
autovalidateMode
,
double
?
menuMaxHeight
,
})
:
assert
(
items
==
null
||
items
.
isEmpty
||
value
==
null
||
items
.
where
((
DropdownMenuItem
<
T
>
item
)
{
return
item
.
value
==
value
;
...
...
@@ -1556,6 +1576,7 @@ class DropdownButtonFormField<T> extends FormField<T> {
focusNode:
focusNode
,
autofocus:
autofocus
,
dropdownColor:
dropdownColor
,
menuMaxHeight:
menuMaxHeight
,
),
),
);
...
...
packages/flutter/test/material/dropdown_test.dart
View file @
e352e086
...
...
@@ -53,6 +53,7 @@ Widget buildDropdown({
bool
autofocus
=
false
,
Color
?
focusColor
,
Color
?
dropdownColor
,
double
?
menuMaxHeight
,
})
{
final
List
<
DropdownMenuItem
<
String
>>?
listItems
=
items
?.
map
<
DropdownMenuItem
<
String
>>((
String
item
)
{
return
DropdownMenuItem
<
String
>(
...
...
@@ -85,6 +86,7 @@ Widget buildDropdown({
items:
listItems
,
selectedItemBuilder:
selectedItemBuilder
,
itemHeight:
itemHeight
,
menuMaxHeight:
menuMaxHeight
,
),
);
}
...
...
@@ -109,6 +111,7 @@ Widget buildDropdown({
items:
listItems
,
selectedItemBuilder:
selectedItemBuilder
,
itemHeight:
itemHeight
,
menuMaxHeight:
menuMaxHeight
,
);
}
...
...
@@ -137,6 +140,7 @@ Widget buildFrame({
Color
?
focusColor
,
Color
?
dropdownColor
,
bool
isFormField
=
false
,
double
?
menuMaxHeight
,
})
{
return
TestApp
(
textDirection:
textDirection
,
...
...
@@ -166,7 +170,9 @@ Widget buildFrame({
dropdownColor:
dropdownColor
,
items:
items
,
selectedItemBuilder:
selectedItemBuilder
,
itemHeight:
itemHeight
,),
itemHeight:
itemHeight
,
menuMaxHeight:
menuMaxHeight
,
),
),
),
),
...
...
@@ -2927,7 +2933,7 @@ void main() {
expect
(
menuItemTapCounters
,
<
int
>[
0
,
2
,
1
,
0
]);
});
testWidgets
(
'
d
oes not crash when option is selected without waiting for opening animation to complete'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'
D
oes not crash when option is selected without waiting for opening animation to complete'
,
(
WidgetTester
tester
)
async
{
// Regression test for b/171846624.
final
List
<
String
>
options
=
<
String
>[
'first'
,
'second'
,
'third'
];
...
...
@@ -3007,6 +3013,59 @@ void main() {
expect
(
find
.
byType
(
Scrollbar
),
paints
..
rect
());
});
testWidgets
(
"Dropdown menu's maximum height should be influenced by DropdownButton.menuMaxHeight."
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
buildFrame
(
value:
'0'
,
items:
List
<
String
>.
generate
(
/*length=*/
64
,
(
int
index
)
=>
index
.
toString
()),
onChanged:
onChanged
,
));
await
tester
.
tap
(
find
.
text
(
'0'
));
await
tester
.
pumpAndSettle
();
final
Element
element
=
tester
.
element
(
find
.
byType
(
ListView
));
double
menuHeight
=
element
.
size
!.
height
;
// The default maximum height should be one item height from the edge.
// https://material.io/design/components/menus.html#usage
final
double
mediaHeight
=
MediaQuery
.
of
(
element
).
size
.
height
;
final
double
defaultMenuHeight
=
mediaHeight
-
(
2
*
kMinInteractiveDimension
);
expect
(
menuHeight
,
defaultMenuHeight
);
await
tester
.
tap
(
find
.
text
(
'0'
).
last
);
await
tester
.
pumpAndSettle
();
// Set menuMaxHeight which is less than defaultMenuHeight
await
tester
.
pumpWidget
(
buildFrame
(
value:
'0'
,
items:
List
<
String
>.
generate
(
/*length=*/
64
,
(
int
index
)
=>
index
.
toString
()),
onChanged:
onChanged
,
menuMaxHeight:
7
*
kMinInteractiveDimension
,
));
await
tester
.
tap
(
find
.
text
(
'0'
));
await
tester
.
pumpAndSettle
();
menuHeight
=
tester
.
element
(
find
.
byType
(
ListView
)).
size
!.
height
;
expect
(
menuHeight
==
defaultMenuHeight
,
isFalse
);
expect
(
menuHeight
,
kMinInteractiveDimension
*
7
);
await
tester
.
tap
(
find
.
text
(
'0'
).
last
);
await
tester
.
pumpAndSettle
();
// Set menuMaxHeight which is greater than defaultMenuHeight
await
tester
.
pumpWidget
(
buildFrame
(
value:
'0'
,
items:
List
<
String
>.
generate
(
/*length=*/
64
,
(
int
index
)
=>
index
.
toString
()),
onChanged:
onChanged
,
menuMaxHeight:
mediaHeight
,
));
await
tester
.
tap
(
find
.
text
(
'0'
));
await
tester
.
pumpAndSettle
();
menuHeight
=
tester
.
element
(
find
.
byType
(
ListView
)).
size
!.
height
;
expect
(
menuHeight
,
defaultMenuHeight
);
});
// Regression test for https://github.com/flutter/flutter/issues/76614
testWidgets
(
'Do not crash if used in very short screen'
,
(
WidgetTester
tester
)
async
{
// The default item height is 48.0 pixels and needs two items padding since
...
...
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