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
4022864c
Unverified
Commit
4022864c
authored
Aug 29, 2023
by
Hans Muller
Committed by
GitHub
Aug 29, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added DropdownMenuEntry.labelWidget (#133491)
parent
89310eda
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
259 additions
and
2 deletions
+259
-2
dropdown_menu_entry_label_widget.0.dart
...ial/dropdown_menu/dropdown_menu_entry_label_widget.0.dart
+91
-0
dropdown_menu_entry_label_widget.0_test.dart
...ropdown_menu/dropdown_menu_entry_label_widget.0_test.dart
+36
-0
dropdown_menu.dart
packages/flutter/lib/src/material/dropdown_menu.dart
+23
-2
dropdown_menu_test.dart
packages/flutter/test/material/dropdown_menu_test.dart
+109
-0
No files found.
examples/api/lib/material/dropdown_menu/dropdown_menu_entry_label_widget.0.dart
0 → 100644
View file @
4022864c
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'package:flutter/material.dart'
;
/// Flutter code sample for the [DropdownMenuEntry] `labelWidget` property.
enum
ColorItem
{
blue
(
'Blue'
,
Colors
.
blue
),
pink
(
'Pink'
,
Colors
.
pink
),
green
(
'Green'
,
Colors
.
green
),
yellow
(
'Yellow'
,
Colors
.
yellow
),
grey
(
'Grey'
,
Colors
.
grey
);
const
ColorItem
(
this
.
label
,
this
.
color
);
final
String
label
;
final
Color
color
;
}
class
DropdownMenuEntryLabelWidgetExample
extends
StatefulWidget
{
const
DropdownMenuEntryLabelWidgetExample
({
super
.
key
});
@override
State
<
DropdownMenuEntryLabelWidgetExample
>
createState
()
=>
_DropdownMenuEntryLabelWidgetExampleState
();
}
class
_DropdownMenuEntryLabelWidgetExampleState
extends
State
<
DropdownMenuEntryLabelWidgetExample
>
{
late
final
TextEditingController
controller
;
@override
void
initState
()
{
super
.
initState
();
controller
=
TextEditingController
();
}
@override
void
dispose
()
{
controller
.
dispose
();
super
.
dispose
();
}
@override
Widget
build
(
BuildContext
context
)
{
// Created by Google Bard from 'create a lyrical phrase of about 25 words that begins with "is a color"'.
const
String
longText
=
'is a color that sings of hope, A hue that shines like gold. It is the color of dreams, A shade that never grows old.'
;
return
Scaffold
(
body:
Center
(
child:
DropdownMenu
<
ColorItem
>(
width:
300
,
controller:
controller
,
initialSelection:
ColorItem
.
green
,
label:
const
Text
(
'Color'
),
onSelected:
(
ColorItem
?
color
)
{
print
(
'Selected
$color
'
);
},
dropdownMenuEntries:
ColorItem
.
values
.
map
<
DropdownMenuEntry
<
ColorItem
>>((
ColorItem
item
)
{
final
String
labelText
=
'
${item.label}
$longText
\n
'
;
return
DropdownMenuEntry
<
ColorItem
>(
value:
item
,
label:
labelText
,
// Try commenting the labelWidget out or changing
// the labelWidget's Text parameters.
labelWidget:
Text
(
labelText
,
maxLines:
1
,
overflow:
TextOverflow
.
ellipsis
,
),
);
}).
toList
(),
),
),
);
}
}
class
DropdownMenuEntryLabelWidgetExampleApp
extends
StatelessWidget
{
const
DropdownMenuEntryLabelWidgetExampleApp
({
super
.
key
});
@override
Widget
build
(
BuildContext
context
)
{
return
const
MaterialApp
(
home:
DropdownMenuEntryLabelWidgetExample
(),
);
}
}
void
main
(
)
{
runApp
(
const
DropdownMenuEntryLabelWidgetExampleApp
());
}
examples/api/test/material/dropdown_menu/dropdown_menu_entry_label_widget.0_test.dart
0 → 100644
View file @
4022864c
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'package:flutter/material.dart'
;
import
'package:flutter_api_samples/material/dropdown_menu/dropdown_menu_entry_label_widget.0.dart'
as
example
;
import
'package:flutter_test/flutter_test.dart'
;
void
main
(
)
{
testWidgets
(
'DropdownEntryLabelWidget appears'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
const
example
.
DropdownMenuEntryLabelWidgetExampleApp
(),
);
const
String
longText
=
'is a color that sings of hope, A hue that shines like gold. It is the color of dreams, A shade that never grows old.'
;
Finder
findMenuItemText
(
String
label
)
{
final
String
labelText
=
'
$label
$longText
\n
'
;
return
find
.
descendant
(
of:
find
.
widgetWithText
(
MenuItemButton
,
labelText
),
matching:
find
.
byType
(
Text
),
).
last
;
}
// Open the menu
await
tester
.
tap
(
find
.
byType
(
TextField
));
expect
(
findMenuItemText
(
'Blue'
),
findsOneWidget
);
expect
(
findMenuItemText
(
'Pink'
),
findsOneWidget
);
expect
(
findMenuItemText
(
'Green'
),
findsOneWidget
);
expect
(
findMenuItemText
(
'Yellow'
),
findsOneWidget
);
expect
(
findMenuItemText
(
'Grey'
),
findsOneWidget
);
// Close the menu
await
tester
.
tap
(
find
.
byType
(
TextField
));
await
tester
.
pumpAndSettle
();
});
}
packages/flutter/lib/src/material/dropdown_menu.dart
View file @
4022864c
...
@@ -44,6 +44,7 @@ class DropdownMenuEntry<T> {
...
@@ -44,6 +44,7 @@ class DropdownMenuEntry<T> {
const
DropdownMenuEntry
({
const
DropdownMenuEntry
({
required
this
.
value
,
required
this
.
value
,
required
this
.
label
,
required
this
.
label
,
this
.
labelWidget
,
this
.
leadingIcon
,
this
.
leadingIcon
,
this
.
trailingIcon
,
this
.
trailingIcon
,
this
.
enabled
=
true
,
this
.
enabled
=
true
,
...
@@ -58,6 +59,17 @@ class DropdownMenuEntry<T> {
...
@@ -58,6 +59,17 @@ class DropdownMenuEntry<T> {
/// The label displayed in the center of the menu item.
/// The label displayed in the center of the menu item.
final
String
label
;
final
String
label
;
/// Overrides the default label widget which is `Text(label)`.
///
/// {@tool dartpad}
/// This sample shows how to override the default label [Text]
/// widget with one that forces the menu entry to appear on one line
/// by specifying [Text.maxLines] and [Text.overflow].
///
/// ** See code in examples/api/lib/material/dropdown_menu/dropdown_menu_entry_label_widget.0.dart **
/// {@end-tool}
final
Widget
?
labelWidget
;
/// An optional icon to display before the label.
/// An optional icon to display before the label.
final
Widget
?
leadingIcon
;
final
Widget
?
leadingIcon
;
...
@@ -441,6 +453,15 @@ class _DropdownMenuState<T> extends State<DropdownMenu<T>> {
...
@@ -441,6 +453,15 @@ class _DropdownMenuState<T> extends State<DropdownMenu<T>> {
final
Color
focusedBackgroundColor
=
effectiveStyle
.
foregroundColor
?.
resolve
(<
MaterialState
>{
MaterialState
.
focused
})
final
Color
focusedBackgroundColor
=
effectiveStyle
.
foregroundColor
?.
resolve
(<
MaterialState
>{
MaterialState
.
focused
})
??
Theme
.
of
(
context
).
colorScheme
.
onSurface
;
??
Theme
.
of
(
context
).
colorScheme
.
onSurface
;
Widget
label
=
entry
.
labelWidget
??
Text
(
entry
.
label
);
if
(
widget
.
width
!=
null
)
{
final
double
horizontalPadding
=
padding
+
_kDefaultHorizontalPadding
;
label
=
ConstrainedBox
(
constraints:
BoxConstraints
(
maxWidth:
widget
.
width
!
-
horizontalPadding
),
child:
label
,
);
}
// Simulate the focused state because the text field should always be focused
// Simulate the focused state because the text field should always be focused
// during traversal. If the menu item has a custom foreground color, the "focused"
// during traversal. If the menu item has a custom foreground color, the "focused"
// color will also change to foregroundColor.withOpacity(0.12).
// color will also change to foregroundColor.withOpacity(0.12).
...
@@ -450,7 +471,7 @@ class _DropdownMenuState<T> extends State<DropdownMenu<T>> {
...
@@ -450,7 +471,7 @@ class _DropdownMenuState<T> extends State<DropdownMenu<T>> {
)
)
:
effectiveStyle
;
:
effectiveStyle
;
final
MenuItemButton
menuItemButton
=
MenuItemButton
(
final
Widget
menuItemButton
=
MenuItemButton
(
key:
enableScrollToHighlight
?
buttonItemKeys
[
i
]
:
null
,
key:
enableScrollToHighlight
?
buttonItemKeys
[
i
]
:
null
,
style:
effectiveStyle
,
style:
effectiveStyle
,
leadingIcon:
entry
.
leadingIcon
,
leadingIcon:
entry
.
leadingIcon
,
...
@@ -465,7 +486,7 @@ class _DropdownMenuState<T> extends State<DropdownMenu<T>> {
...
@@ -465,7 +486,7 @@ class _DropdownMenuState<T> extends State<DropdownMenu<T>> {
}
}
:
null
,
:
null
,
requestFocusOnHover:
false
,
requestFocusOnHover:
false
,
child:
Text
(
entry
.
label
)
,
child:
label
,
);
);
result
.
add
(
menuItemButton
);
result
.
add
(
menuItemButton
);
}
}
...
...
packages/flutter/test/material/dropdown_menu_test.dart
View file @
4022864c
...
@@ -10,6 +10,7 @@ import 'package:flutter/services.dart';
...
@@ -10,6 +10,7 @@ import 'package:flutter/services.dart';
import
'package:flutter_test/flutter_test.dart'
;
import
'package:flutter_test/flutter_test.dart'
;
void
main
(
)
{
void
main
(
)
{
const
String
longText
=
'one two three four five six seven eight nine ten eleven twelve'
;
final
List
<
DropdownMenuEntry
<
TestMenu
>>
menuChildren
=
<
DropdownMenuEntry
<
TestMenu
>>[];
final
List
<
DropdownMenuEntry
<
TestMenu
>>
menuChildren
=
<
DropdownMenuEntry
<
TestMenu
>>[];
for
(
final
TestMenu
value
in
TestMenu
.
values
)
{
for
(
final
TestMenu
value
in
TestMenu
.
values
)
{
...
@@ -1571,6 +1572,114 @@ void main() {
...
@@ -1571,6 +1572,114 @@ void main() {
expect
(
material
.
textStyle
?.
wordSpacing
,
menuItemTextThemeStyle
.
wordSpacing
);
expect
(
material
.
textStyle
?.
wordSpacing
,
menuItemTextThemeStyle
.
wordSpacing
);
expect
(
material
.
textStyle
?.
decoration
,
menuItemTextThemeStyle
.
decoration
);
expect
(
material
.
textStyle
?.
decoration
,
menuItemTextThemeStyle
.
decoration
);
});
});
testWidgets
(
'DropdownMenuEntries do not overflow when width is specified'
,
(
WidgetTester
tester
)
async
{
// Regression test for https://github.com/flutter/flutter/issues/126882
final
TextEditingController
controller
=
TextEditingController
();
await
tester
.
pumpWidget
(
MaterialApp
(
home:
Scaffold
(
body:
DropdownMenu
<
TestMenu
>(
controller:
controller
,
width:
100
,
dropdownMenuEntries:
TestMenu
.
values
.
map
<
DropdownMenuEntry
<
TestMenu
>>((
TestMenu
item
)
{
return
DropdownMenuEntry
<
TestMenu
>(
value:
item
,
label:
'
${item.label}
$longText
'
,
);
}).
toList
(),
),
),
),
);
// Opening the width=100 menu should not crash.
await
tester
.
tap
(
find
.
byType
(
DropdownMenu
<
TestMenu
>));
expect
(
tester
.
takeException
(),
isNull
);
await
tester
.
pumpAndSettle
();
Finder
findMenuItemText
(
String
label
)
{
final
String
labelText
=
'
$label
$longText
'
;
return
find
.
descendant
(
of:
find
.
widgetWithText
(
MenuItemButton
,
labelText
),
matching:
find
.
byType
(
Text
),
).
last
;
}
// Actual size varies a little on web platforms.
final
Matcher
closeTo300
=
closeTo
(
300
,
0.25
);
expect
(
tester
.
getSize
(
findMenuItemText
(
'Item 0'
)).
height
,
closeTo300
);
expect
(
tester
.
getSize
(
findMenuItemText
(
'Menu 1'
)).
height
,
closeTo300
);
expect
(
tester
.
getSize
(
findMenuItemText
(
'Item 2'
)).
height
,
closeTo300
);
expect
(
tester
.
getSize
(
findMenuItemText
(
'Item 3'
)).
height
,
closeTo300
);
await
tester
.
tap
(
findMenuItemText
(
'Item 0'
));
await
tester
.
pumpAndSettle
();
expect
(
controller
.
text
,
'Item 0
$longText
'
);
});
testWidgets
(
'DropdownMenuEntry.labelWidget is Text that specifies maxLines 1 or 2'
,
(
WidgetTester
tester
)
async
{
// Regression test for https://github.com/flutter/flutter/issues/126882
final
TextEditingController
controller
=
TextEditingController
();
Widget
buildFrame
({
required
int
maxLines
})
{
return
MaterialApp
(
home:
Scaffold
(
body:
DropdownMenu
<
TestMenu
>(
key:
ValueKey
<
int
>(
maxLines
),
controller:
controller
,
width:
100
,
dropdownMenuEntries:
TestMenu
.
values
.
map
<
DropdownMenuEntry
<
TestMenu
>>((
TestMenu
item
)
{
return
DropdownMenuEntry
<
TestMenu
>(
value:
item
,
label:
'
${item.label}
$longText
'
,
labelWidget:
Text
(
'
${item.label}
$longText
'
,
maxLines:
maxLines
),
);
}).
toList
(),
),
)
);
}
Finder
findMenuItemText
(
String
label
)
{
final
String
labelText
=
'
$label
$longText
'
;
return
find
.
descendant
(
of:
find
.
widgetWithText
(
MenuItemButton
,
labelText
),
matching:
find
.
byType
(
Text
),
).
last
;
}
await
tester
.
pumpWidget
(
buildFrame
(
maxLines:
1
));
await
tester
.
tap
(
find
.
byType
(
DropdownMenu
<
TestMenu
>));
// Actual size varies a little on web platforms.
final
Matcher
closeTo20
=
closeTo
(
20
,
0.05
);
expect
(
tester
.
getSize
(
findMenuItemText
(
'Item 0'
)).
height
,
closeTo20
);
expect
(
tester
.
getSize
(
findMenuItemText
(
'Menu 1'
)).
height
,
closeTo20
);
expect
(
tester
.
getSize
(
findMenuItemText
(
'Item 2'
)).
height
,
closeTo20
);
expect
(
tester
.
getSize
(
findMenuItemText
(
'Item 3'
)).
height
,
closeTo20
);
// Close the menu
await
tester
.
tap
(
find
.
byType
(
TextField
));
await
tester
.
pumpAndSettle
();
expect
(
controller
.
text
,
''
);
// nothing selected
await
tester
.
pumpWidget
(
buildFrame
(
maxLines:
2
));
await
tester
.
tap
(
find
.
byType
(
DropdownMenu
<
TestMenu
>));
// Actual size varies a little on web platforms.
final
Matcher
closeTo40
=
closeTo
(
40
,
0.05
);
expect
(
tester
.
getSize
(
findMenuItemText
(
'Item 0'
)).
height
,
closeTo40
);
expect
(
tester
.
getSize
(
findMenuItemText
(
'Menu 1'
)).
height
,
closeTo40
);
expect
(
tester
.
getSize
(
findMenuItemText
(
'Item 2'
)).
height
,
closeTo40
);
expect
(
tester
.
getSize
(
findMenuItemText
(
'Item 3'
)).
height
,
closeTo40
);
// Close the menu
await
tester
.
tap
(
find
.
byType
(
TextField
));
await
tester
.
pumpAndSettle
();
expect
(
controller
.
text
,
''
);
// nothing selected
});
}
}
enum
TestMenu
{
enum
TestMenu
{
...
...
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