@@ -537,17 +537,15 @@ class _RenderMenuItem extends RenderProxyBox {
537537 }
538538}
539539
540- /// An item in a menu created by a [DropdownButton] .
541- ///
542- /// The type `T` is the type of the value the entry represents. All the entries
543- /// in a given menu must represent values with consistent types.
544- class DropdownMenuItem <T > extends StatelessWidget {
540+ // The container widget for a menu item created by a [DropdownButton]. It
541+ // provides the default configuration for [DropdownMenuItem]s, as well as a
542+ // [DropdownButton]'s hint and disabledHint widgets.
543+ class _DropdownMenuItemContainer extends StatelessWidget {
545544 /// Creates an item for a dropdown menu.
546545 ///
547546 /// The [child] argument is required.
548- const DropdownMenuItem ({
547+ const _DropdownMenuItemContainer ({
549548 Key key,
550- this .value,
551549 @required this .child,
552550 }) : assert (child != null ),
553551 super (key: key);
@@ -557,11 +555,6 @@ class DropdownMenuItem<T> extends StatelessWidget {
557555 /// Typically a [Text] widget.
558556 final Widget child;
559557
560- /// The value to return if the user selects this menu item.
561- ///
562- /// Eventually returned in a call to [DropdownButton.onChanged] .
563- final T value;
564-
565558 @override
566559 Widget build (BuildContext context) {
567560 return Container (
@@ -572,6 +565,27 @@ class DropdownMenuItem<T> extends StatelessWidget {
572565 }
573566}
574567
568+ /// An item in a menu created by a [DropdownButton] .
569+ ///
570+ /// The type `T` is the type of the value the entry represents. All the entries
571+ /// in a given menu must represent values with consistent types.
572+ class DropdownMenuItem <T > extends _DropdownMenuItemContainer {
573+ /// Creates an item for a dropdown menu.
574+ ///
575+ /// The [child] argument is required.
576+ const DropdownMenuItem ({
577+ Key key,
578+ this .value,
579+ @required Widget child,
580+ }) : assert (child != null ),
581+ super (key: key, child: child);
582+
583+ /// The value to return if the user selects this menu item.
584+ ///
585+ /// Eventually returned in a call to [DropdownButton.onChanged] .
586+ final T value;
587+ }
588+
575589/// An inherited widget that causes any descendant [DropdownButton]
576590/// widgets to not include their regular underline.
577591///
@@ -658,7 +672,9 @@ class DropdownButtonHideUnderline extends InheritedWidget {
658672/// If the [onChanged] callback is null or the list of [items] is null
659673/// then the dropdown button will be disabled, i.e. its arrow will be
660674/// displayed in grey and it will not respond to input. A disabled button
661- /// will display the [disabledHint] widget if it is non-null.
675+ /// will display the [disabledHint] widget if it is non-null. However, if
676+ /// [disabledHint] is null and [hint] is non-null, the [hint] widget will
677+ /// instead be displayed.
662678///
663679/// Requires one of its ancestors to be a [Material] widget.
664680///
@@ -676,6 +692,8 @@ class DropdownButton<T> extends StatefulWidget {
676692 /// must be equal to one of the [DropDownMenuItem] values. If [items] or
677693 /// [onChanged] is null, the button will be disabled, the down arrow
678694 /// will be greyed out, and the [disabledHint] will be shown (if provided).
695+ /// If [disabledHint] is null and [hint] is non-null, [hint] will instead be
696+ /// shown.
679697 ///
680698 /// The [elevation] and [iconSize] arguments must not be null (they both have
681699 /// defaults, so do not need to be specified). The boolean [isDense] and
@@ -715,20 +733,28 @@ class DropdownButton<T> extends StatefulWidget {
715733 /// If the [onChanged] callback is null or the list of items is null
716734 /// then the dropdown button will be disabled, i.e. its arrow will be
717735 /// displayed in grey and it will not respond to input. A disabled button
718- /// will display the [disabledHint] widget if it is non-null.
736+ /// will display the [disabledHint] widget if it is non-null. If
737+ /// [disabledHint] is also null but [hint] is non-null, [hint] will instead
738+ /// be displayed.
719739 final List <DropdownMenuItem <T >> items;
720740
721- /// The value of the currently selected [DropdownMenuItem] , or null if no
722- /// item has been selected. If `value` is null then the menu is popped up as
723- /// if the first item were selected.
741+ /// The value of the currently selected [DropdownMenuItem] .
742+ ///
743+ /// If [value] is null and [hint] is non-null, the [hint] widget is
744+ /// displayed as a placeholder for the dropdown button's value.
724745 final T value;
725746
726- /// A placeholder widget that is displayed if no item is selected, i.e. if [value] is null.
747+ /// A placeholder widget that is displayed by the dropdown button.
748+ ///
749+ /// If [value] is null, this widget is displayed as a placeholder for
750+ /// the dropdown button's value. This widget is also displayed if the button
751+ /// is disabled ([items] or [onChanged] is null) and [disabledHint] is null.
727752 final Widget hint;
728753
729754 /// A message to show when the dropdown is disabled.
730755 ///
731- /// Displayed if [items] or [onChanged] is null.
756+ /// Displayed if [items] or [onChanged] is null. If [hint] is non-null and
757+ /// [disabledHint] is null, the [hint] widget will be displayed instead.
732758 final Widget disabledHint;
733759
734760 /// {@template flutter.material.dropdownButton.onChanged}
@@ -737,7 +763,9 @@ class DropdownButton<T> extends StatefulWidget {
737763 /// If the [onChanged] callback is null or the list of [items] is null
738764 /// then the dropdown button will be disabled, i.e. its arrow will be
739765 /// displayed in grey and it will not respond to input. A disabled button
740- /// will display the [disabledHint] widget if it is non-null.
766+ /// will display the [disabledHint] widget if it is non-null. If
767+ /// [disabledHint] is also null but [hint] is non-null, [hint] will instead
768+ /// be displayed.
741769 /// {@endtemplate}
742770 final ValueChanged <T > onChanged;
743771
@@ -1113,28 +1141,25 @@ class _DropdownButtonState<T> extends State<DropdownButton<T>> with WidgetsBindi
11131141 if (_enabled) {
11141142 items = widget.selectedItemBuilder == null
11151143 ? List <Widget >.from (widget.items)
1116- : widget.selectedItemBuilder (context).map <Widget >((Widget item) {
1117- return Container (
1118- constraints: const BoxConstraints (minHeight: _kMenuItemHeight),
1119- alignment: AlignmentDirectional .centerStart,
1120- child: item,
1121- );
1122- }).toList ();
1144+ : widget.selectedItemBuilder (context);
11231145 } else {
1124- items = < Widget > [];
1146+ items = widget.selectedItemBuilder == null
1147+ ? < Widget > []
1148+ : widget.selectedItemBuilder (context);
11251149 }
11261150
11271151 int hintIndex;
11281152 if (widget.hint != null || (! _enabled && widget.disabledHint != null )) {
1129- final Widget emplacedHint = _enabled
1130- ? widget.hint
1131- : DropdownMenuItem <Widget >(child: widget.disabledHint ?? widget.hint);
1153+ Widget displayedHint = _enabled ? widget.hint : widget.disabledHint ?? widget.hint;
1154+ if (widget.selectedItemBuilder == null )
1155+ displayedHint = _DropdownMenuItemContainer (child: displayedHint);
1156+
11321157 hintIndex = items.length;
11331158 items.add (DefaultTextStyle (
11341159 style: _textStyle.copyWith (color: Theme .of (context).hintColor),
11351160 child: IgnorePointer (
1136- child: emplacedHint,
11371161 ignoringSemantics: false ,
1162+ child: displayedHint,
11381163 ),
11391164 ));
11401165 }
0 commit comments