Commit 7667a3f8 authored by Hans Muller's avatar Hans Muller Committed by GitHub

DropdownButton hint (#7114)

parent a9584e12
...@@ -132,7 +132,8 @@ class _ButtonsDemoState extends State<ButtonsDemo> { ...@@ -132,7 +132,8 @@ class _ButtonsDemoState extends State<ButtonsDemo> {
// https://en.wikipedia.org/wiki/Free_Four // https://en.wikipedia.org/wiki/Free_Four
String dropdown1Value = 'Free'; String dropdown1Value = 'Free';
String dropdown2Value = 'Four'; String dropdown2Value;
String dropdown3Value = 'Four';
Widget buildDropdownButton() { Widget buildDropdownButton() {
return new Padding( return new Padding(
...@@ -141,7 +142,7 @@ class _ButtonsDemoState extends State<ButtonsDemo> { ...@@ -141,7 +142,7 @@ class _ButtonsDemoState extends State<ButtonsDemo> {
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[ children: <Widget>[
new ListItem( new ListItem(
title: new Text('Scrollable dropdown:'), title: new Text('Simple dropdown:'),
trailing: new DropdownButton<String>( trailing: new DropdownButton<String>(
value: dropdown1Value, value: dropdown1Value,
onChanged: (String newValue) { onChanged: (String newValue) {
...@@ -149,26 +150,22 @@ class _ButtonsDemoState extends State<ButtonsDemo> { ...@@ -149,26 +150,22 @@ class _ButtonsDemoState extends State<ButtonsDemo> {
dropdown1Value = newValue; dropdown1Value = newValue;
}); });
}, },
items: <String>[ items: <String>['One', 'Two', 'Free', 'Four'].map((String value) {
'One', 'Two', 'Free', 'Four', 'Can', 'I', 'Have', 'A', 'Little', return new DropdownMenuItem<String>(
'Bit', 'More', 'Five', 'Six', 'Seven', 'Eight', 'Nine', 'Ten' value: value,
] child: new Text(value),
.map((String value) { );
return new DropdownMenuItem<String>( }).toList(),
value: value, ),
child: new Text(value),
);
})
.toList(),
),
), ),
new SizedBox( new SizedBox(
height: 24.0, height: 24.0,
), ),
new ListItem( new ListItem(
title: new Text('Simple dropdown:'), title: new Text('Dropdown with a hint:'),
trailing: new DropdownButton<String>( trailing: new DropdownButton<String>(
value: dropdown2Value, value: dropdown2Value,
hint: new Text('Choose'),
onChanged: (String newValue) { onChanged: (String newValue) {
setState(() { setState(() {
dropdown2Value = newValue; dropdown2Value = newValue;
...@@ -181,7 +178,32 @@ class _ButtonsDemoState extends State<ButtonsDemo> { ...@@ -181,7 +178,32 @@ class _ButtonsDemoState extends State<ButtonsDemo> {
); );
}).toList(), }).toList(),
), ),
) ),
new SizedBox(
height: 24.0,
),
new ListItem(
title: new Text('Scrollable dropdown:'),
trailing: new DropdownButton<String>(
value: dropdown3Value,
onChanged: (String newValue) {
setState(() {
dropdown3Value = newValue;
});
},
items: <String>[
'One', 'Two', 'Free', 'Four', 'Can', 'I', 'Have', 'A', 'Little',
'Bit', 'More', 'Five', 'Six', 'Seven', 'Eight', 'Nine', 'Ten'
]
.map((String value) {
return new DropdownMenuItem<String>(
value: value,
child: new Text(value),
);
})
.toList(),
),
),
], ],
), ),
); );
......
...@@ -420,6 +420,7 @@ class DropdownButton<T> extends StatefulWidget { ...@@ -420,6 +420,7 @@ class DropdownButton<T> extends StatefulWidget {
Key key, Key key,
@required this.items, @required this.items,
this.value, this.value,
this.hint,
@required this.onChanged, @required this.onChanged,
this.elevation: 8, this.elevation: 8,
this.style, this.style,
...@@ -439,6 +440,9 @@ class DropdownButton<T> extends StatefulWidget { ...@@ -439,6 +440,9 @@ class DropdownButton<T> extends StatefulWidget {
/// selected. /// selected.
final T value; final T value;
/// Displayed if [value] is null.
final Widget hint;
/// Called when the user selects an item. /// Called when the user selects an item.
final ValueChanged<T> onChanged; final ValueChanged<T> onChanged;
...@@ -530,6 +534,21 @@ class _DropdownButtonState<T> extends State<DropdownButton<T>> { ...@@ -530,6 +534,21 @@ class _DropdownButtonState<T> extends State<DropdownButton<T>> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
assert(debugCheckHasMaterial(context)); assert(debugCheckHasMaterial(context));
// The width of the button and the menu are defined by the widest
// item and the width of the hint.
final List<Widget> items = new List<Widget>.from(config.items);
int hintIndex;
if (config.hint != null) {
hintIndex = items.length;
items.add(new DefaultTextStyle(
style: _textStyle.copyWith(color: Theme.of(context).hintColor),
child: new IgnorePointer(
child: config.hint,
),
));
}
Widget result = new DefaultTextStyle( Widget result = new DefaultTextStyle(
style: _textStyle, style: _textStyle,
child: new SizedBox( child: new SizedBox(
...@@ -538,12 +557,12 @@ class _DropdownButtonState<T> extends State<DropdownButton<T>> { ...@@ -538,12 +557,12 @@ class _DropdownButtonState<T> extends State<DropdownButton<T>> {
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: <Widget>[ children: <Widget>[
// The button's size is defined by its largest menu item. If value is // If value is null (then _selectedIndex is null) then we display
// null then an item does not appear. // the hint or nothing at all.
new IndexedStack( new IndexedStack(
index: _selectedIndex, index: _selectedIndex ?? hintIndex,
alignment: FractionalOffset.centerLeft, alignment: FractionalOffset.centerLeft,
children: config.items, children: items,
), ),
new Icon(Icons.arrow_drop_down, new Icon(Icons.arrow_drop_down,
size: config.iconSize, size: config.iconSize,
...@@ -568,10 +587,10 @@ class _DropdownButtonState<T> extends State<DropdownButton<T>> { ...@@ -568,10 +587,10 @@ class _DropdownButtonState<T> extends State<DropdownButton<T>> {
height: 1.0, height: 1.0,
decoration: const BoxDecoration( decoration: const BoxDecoration(
border: const Border(bottom: const BorderSide(color: const Color(0xFFBDBDBD), width: 0.0)) border: const Border(bottom: const BorderSide(color: const Color(0xFFBDBDBD), width: 0.0))
) ),
) ),
) ),
] ],
); );
} }
......
...@@ -9,13 +9,20 @@ import 'package:flutter/material.dart'; ...@@ -9,13 +9,20 @@ import 'package:flutter/material.dart';
final List<String> menuItems = <String>['one', 'two', 'three', 'four']; final List<String> menuItems = <String>['one', 'two', 'three', 'four'];
Widget buildFrame({ Key buttonKey, String value: 'two', ValueChanged<String> onChanged, bool isDense: false }) { Widget buildFrame({
Key buttonKey,
String value: 'two',
ValueChanged<String> onChanged,
bool isDense: false,
Widget hint,
}) {
return new MaterialApp( return new MaterialApp(
home: new Material( home: new Material(
child: new Center( child: new Center(
child: new DropdownButton<String>( child: new DropdownButton<String>(
key: buttonKey, key: buttonKey,
value: value, value: value,
hint: hint,
onChanged: onChanged, onChanged: onChanged,
isDense: isDense, isDense: isDense,
items: menuItems.map((String item) { items: menuItems.map((String item) {
...@@ -317,4 +324,28 @@ void main() { ...@@ -317,4 +324,28 @@ void main() {
expect(value, equals('one')); expect(value, equals('one'));
}); });
testWidgets('Size of DropdownButton with null value and a hint', (WidgetTester tester) async {
Key buttonKey = new UniqueKey();
String value;
// The hint will define the dropdown's width
Widget build() => buildFrame(buttonKey: buttonKey, value: value, hint: new Text('onetwothree'));
await tester.pumpWidget(build());
expect(find.text('onetwothree'), findsOneWidget);
RenderBox buttonBoxHintValue = tester.renderObject(find.byKey(buttonKey));
assert(buttonBoxHintValue.attached);
value = 'three';
await tester.pumpWidget(build());
RenderBox buttonBox = tester.renderObject(find.byKey(buttonKey));
assert(buttonBox.attached);
// A DropDown button with a null value and a hint should be the same size as a
// one with a non-null value.
expect(buttonBox.localToGlobal(Point.origin), equals(buttonBoxHintValue.localToGlobal(Point.origin)));
expect(buttonBox.size, equals(buttonBoxHintValue.size));
});
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment