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> {
// https://en.wikipedia.org/wiki/Free_Four
String dropdown1Value = 'Free';
String dropdown2Value = 'Four';
String dropdown2Value;
String dropdown3Value = 'Four';
Widget buildDropdownButton() {
return new Padding(
......@@ -141,7 +142,7 @@ class _ButtonsDemoState extends State<ButtonsDemo> {
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
new ListItem(
title: new Text('Scrollable dropdown:'),
title: new Text('Simple dropdown:'),
trailing: new DropdownButton<String>(
value: dropdown1Value,
onChanged: (String newValue) {
......@@ -149,26 +150,22 @@ class _ButtonsDemoState extends State<ButtonsDemo> {
dropdown1Value = 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(),
),
items: <String>['One', 'Two', 'Free', 'Four'].map((String value) {
return new DropdownMenuItem<String>(
value: value,
child: new Text(value),
);
}).toList(),
),
),
new SizedBox(
height: 24.0,
),
new ListItem(
title: new Text('Simple dropdown:'),
title: new Text('Dropdown with a hint:'),
trailing: new DropdownButton<String>(
value: dropdown2Value,
hint: new Text('Choose'),
onChanged: (String newValue) {
setState(() {
dropdown2Value = newValue;
......@@ -181,7 +178,32 @@ class _ButtonsDemoState extends State<ButtonsDemo> {
);
}).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 {
Key key,
@required this.items,
this.value,
this.hint,
@required this.onChanged,
this.elevation: 8,
this.style,
......@@ -439,6 +440,9 @@ class DropdownButton<T> extends StatefulWidget {
/// selected.
final T value;
/// Displayed if [value] is null.
final Widget hint;
/// Called when the user selects an item.
final ValueChanged<T> onChanged;
......@@ -530,6 +534,21 @@ class _DropdownButtonState<T> extends State<DropdownButton<T>> {
@override
Widget build(BuildContext 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(
style: _textStyle,
child: new SizedBox(
......@@ -538,12 +557,12 @@ class _DropdownButtonState<T> extends State<DropdownButton<T>> {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
// The button's size is defined by its largest menu item. If value is
// null then an item does not appear.
// If value is null (then _selectedIndex is null) then we display
// the hint or nothing at all.
new IndexedStack(
index: _selectedIndex,
index: _selectedIndex ?? hintIndex,
alignment: FractionalOffset.centerLeft,
children: config.items,
children: items,
),
new Icon(Icons.arrow_drop_down,
size: config.iconSize,
......@@ -568,10 +587,10 @@ class _DropdownButtonState<T> extends State<DropdownButton<T>> {
height: 1.0,
decoration: const BoxDecoration(
border: const Border(bottom: const BorderSide(color: const Color(0xFFBDBDBD), width: 0.0))
)
)
)
]
),
),
),
],
);
}
......
......@@ -9,13 +9,20 @@ import 'package:flutter/material.dart';
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(
home: new Material(
child: new Center(
child: new DropdownButton<String>(
key: buttonKey,
value: value,
hint: hint,
onChanged: onChanged,
isDense: isDense,
items: menuItems.map((String item) {
......@@ -317,4 +324,28 @@ void main() {
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