Unverified Commit 9a290c17 authored by Michael Klimushyn's avatar Michael Klimushyn Committed by GitHub

Expand DropdownButton width based on isExpanded flag (#21515)

* Fix Dropdown where icon not set to end of button

* Expand DropdownButton based on isExpanded flag

* Add dropdown golden tests

Fixes #13135, #16606
parent 05d557b9
555a2f96848c31b8c0303555535d6b5e20686e6e
5b0696a651738116b4d25a5b0a946b0951e45e6f
......@@ -484,6 +484,7 @@ class DropdownButton<T> extends StatefulWidget {
this.style,
this.iconSize = 24.0,
this.isDense = false,
this.isExpanded = false,
}) : assert(items != null),
assert(value == null || items.where((DropdownMenuItem<T> item) => item.value == value).length == 1),
super(key: key);
......@@ -529,6 +530,13 @@ class DropdownButton<T> extends StatefulWidget {
/// its own decorations, like [InputDecorator].
final bool isDense;
/// Set the dropdown's inner contents to horizontally fill its parent.
///
/// By default this button's inner width is the minimum size of its contents.
/// If [isExpanded] is true, the inner width is expanded to fill its
/// surrounding container.
final bool isExpanded;
@override
_DropdownButtonState<T> createState() => new _DropdownButtonState<T>();
}
......@@ -643,6 +651,14 @@ class _DropdownButtonState<T> extends State<DropdownButton<T>> with WidgetsBindi
? _kAlignedButtonPadding
: _kUnalignedButtonPadding;
// If value is null (then _selectedIndex is null) then we display
// the hint or nothing at all.
final IndexedStack innerItemsWidget = new IndexedStack(
index: _selectedIndex ?? hintIndex,
alignment: AlignmentDirectional.centerStart,
children: items,
);
Widget result = new DefaultTextStyle(
style: _textStyle,
child: new Container(
......@@ -652,13 +668,7 @@ class _DropdownButtonState<T> extends State<DropdownButton<T>> with WidgetsBindi
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
// If value is null (then _selectedIndex is null) then we display
// the hint or nothing at all.
new IndexedStack(
index: _selectedIndex ?? hintIndex,
alignment: AlignmentDirectional.centerStart,
children: items,
),
widget.isExpanded ? new Expanded(child: innerItemsWidget) : innerItemsWidget,
new Icon(Icons.arrow_drop_down,
size: widget.iconSize,
// These colors are not defined in the Material Design spec.
......
......@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:io';
import 'dart:math' as math;
import 'dart:ui' show window;
......@@ -23,6 +24,7 @@ Widget buildFrame({
String value = 'two',
ValueChanged<String> onChanged,
bool isDense = false,
bool isExpanded = false,
Widget hint,
List<String> items = menuItems,
Alignment alignment = Alignment.center,
......@@ -33,19 +35,22 @@ Widget buildFrame({
child: new Material(
child: new Align(
alignment: alignment,
child: new DropdownButton<String>(
key: buttonKey,
value: value,
hint: hint,
onChanged: onChanged,
isDense: isDense,
items: items.map((String item) {
return new DropdownMenuItem<String>(
key: new ValueKey<String>(item),
value: item,
child: new Text(item, key: new ValueKey<String>(item + 'Text')),
);
}).toList(),
child: new RepaintBoundary(
child: new DropdownButton<String>(
key: buttonKey,
value: value,
hint: hint,
onChanged: onChanged,
isDense: isDense,
isExpanded: isExpanded,
items: items.map((String item) {
return new DropdownMenuItem<String>(
key: new ValueKey<String>(item),
value: item,
child: new Text(item, key: new ValueKey<String>(item + 'Text')),
);
}).toList(),
)
),
),
),
......@@ -108,6 +113,32 @@ bool sameGeometry(RenderBox box1, RenderBox box2) {
}
void main() {
testWidgets('Default dropdown golden', (WidgetTester tester) async {
final Key buttonKey = new UniqueKey();
Widget build() => buildFrame(buttonKey: buttonKey, value: 'two');
await tester.pumpWidget(build());
final Finder buttonFinder = find.byKey(buttonKey);
assert(tester.renderObject(buttonFinder).attached);
await expectLater(
find.ancestor(of: buttonFinder, matching: find.byType(RepaintBoundary)).first,
matchesGoldenFile('dropdown_test.default.0.png'),
skip: !Platform.isLinux,
);
});
testWidgets('Expanded dropdown golden', (WidgetTester tester) async {
final Key buttonKey = new UniqueKey();
Widget build() => buildFrame(buttonKey: buttonKey, value: 'two', isExpanded: true);
await tester.pumpWidget(build());
final Finder buttonFinder = find.byKey(buttonKey);
assert(tester.renderObject(buttonFinder).attached);
await expectLater(
find.ancestor(of: buttonFinder, matching: find.byType(RepaintBoundary)).first,
matchesGoldenFile('dropdown_test.expanded.0.png'),
skip: !Platform.isLinux,
);
});
testWidgets('Dropdown button control test', (WidgetTester tester) async {
String value = 'one';
void didChangeValue(String newValue) {
......@@ -337,6 +368,23 @@ void main() {
});
}
testWidgets('Arrow icon aligns with the edge of button when expanded', (WidgetTester tester) async {
final Key buttonKey = new UniqueKey();
Widget build() => buildFrame(buttonKey: buttonKey, value: 'two', isExpanded: true);
await tester.pumpWidget(build());
final RenderBox buttonBox = tester.renderObject(find.byKey(buttonKey));
assert(buttonBox.attached);
final RenderBox arrowIcon = tester.renderObject(find.byIcon(Icons.arrow_drop_down));
assert(arrowIcon.attached);
// Arrow icon should be aligned with far right of button when expanded
expect(arrowIcon.localToGlobal(Offset.zero).dx,
buttonBox.size.centerRight(new Offset(-arrowIcon.size.width, 0.0)).dx);
});
testWidgets('Dropdown button with isDense:true aligns selected menu item', (WidgetTester tester) async {
final Key buttonKey = new UniqueKey();
const String value = 'two';
......
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