Skip to content

Make DropdownButton's disabledHint and hint behavior consistent#42479

Merged
shihaohong merged 9 commits intoflutter:masterfrom
shihaohong:dropdown-disabled-hint
Oct 28, 2019
Merged

Make DropdownButton's disabledHint and hint behavior consistent#42479
shihaohong merged 9 commits intoflutter:masterfrom
shihaohong:dropdown-disabled-hint

Conversation

@shihaohong
Copy link
Contributor

@shihaohong shihaohong commented Oct 10, 2019

Description

This PR brings consistency to DropdownButton's hint behavior in the following ways:

  1. When DropdownButton.selectedItemBuilder = null, it now correctly wraps the hint with a Container with the correct constraints and alignment (To match the defaults of DropdownMenuItem).
  2. When DropdownButton.selectedItemBuilder is defined, hint and disabledHint are no longer wrapped with the constrained Container, allowing for more flexibility in creating the hint and disabledHint widgets.

Related Issues

Fixes #42472
Fixes #43040

Tests

I added the following tests:

  1. DropdownButton.selectedItemBuilder defined
  • size matches largest item in menu items
  • size matches largest item when hint is provided
  • size matches largest item when disabled hint is provided
  1. General tests
  • tests to verify that for disabled dropdown buttons, hint is used when disabledHint is null

Checklist

Before you create this PR confirm that it meets all requirements listed below by checking the relevant checkboxes ([x]). This will ensure a smooth and quick review process.

  • I read the Contributor Guide and followed the process outlined there for submitting PRs.
  • I signed the CLA.
  • I read and followed the Flutter Style Guide, including Features we expect every widget to implement.
  • I updated/added relevant documentation (doc comments with ///).
  • All existing and new tests are passing.
  • The analyzer (flutter analyze --flutter-repo) does not report any problems on my PR.
  • I am willing to follow-up on review comments in a timely manner.

Breaking Change

Does your PR require Flutter developers to manually update their apps to accommodate your change?

  • Yes, this is a breaking change (Please read Handling breaking changes). Replace this with a link to the e-mail where you asked for input on this proposed change.
  • No, this is not a breaking change.

@shihaohong shihaohong added framework flutter/packages/flutter repository. See also f: labels. f: material design flutter/packages/flutter/material repository. labels Oct 10, 2019
@shihaohong shihaohong requested a review from HansMuller October 10, 2019 23:45
@shihaohong shihaohong changed the title Make DropdownButton's disabledHint and hint behavior consistent WIP: Make DropdownButton's disabledHint and hint behavior consistent Oct 10, 2019
@shihaohong shihaohong changed the title WIP: Make DropdownButton's disabledHint and hint behavior consistent Make DropdownButton's disabledHint and hint behavior consistent Oct 10, 2019
}

if (widget.selectedItemBuilder == null) {
displayedHint = Container(
Copy link
Contributor Author

@shihaohong shihaohong Oct 14, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This Container mimics the constraints and alignments for a default menu item, similar to DropdownMenuItem, when selectedItemBuilder is not being used

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would probably be safest to either include a comment here and in DropdownMenuItem.build() indicating that the code must be kept in sync, or add a _DropdownMenuItemContainer widget and use it in both places. The widget approach might be preferable, since you can explain what's going on vis-a-vis selectedItemBuilder in a comment above the widget class.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good, I just added a _DropdownMenuItemContainer and had DropdownMenuItem extend it to keep the code in sync. PTAL

final Widget emplacedHint = _enabled
? widget.hint
: DropdownMenuItem<Widget>(child: widget.disabledHint ?? widget.hint);
Widget displayedHint;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't really matter but this could be:

Widget displayedHint = _enabled ? widget.hint : widget.disabledHint ?? widget.hint;

Also: thank you for eliminating the name "emplacedHint" :-).

}

if (widget.selectedItemBuilder == null) {
displayedHint = Container(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would probably be safest to either include a comment here and in DropdownMenuItem.build() indicating that the code must be kept in sync, or add a _DropdownMenuItemContainer widget and use it in both places. The widget approach might be preferable, since you can explain what's going on vis-a-vis selectedItemBuilder in a comment above the widget class.

);
}).toList(),
selectedItemBuilder: selectedItemBuilder,
itemHeight: itemHeight,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good: tests that don't specify itemHeight should work as before since kMinInteractiveDimension is the default.

int hintIndex;
if (widget.hint != null || (!_enabled && widget.disabledHint != null)) {
final Widget emplacedHint = _enabled
? widget.hint
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previously, an app that specified a hint for an enabled DropdownButton, would not see that hint aligned and its minHeight would not be constrained (because we didn't wrap it). That seems like a pointless inconsistency, but we'll need to watch out for problems introduced by this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right -- this would be the breaking change part of this PR, I think it might still be worth sending an email out to Flutter developers to notify them of the correct fix if they run into problems here

disabledHint: null,
);
}
// [hint] should display when [items] is null and [disabledHint] is not defined
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to https://api.flutter.dev/flutter/material/DropdownButton/hint.html, the hint is displayed if value is null.

There seems to be some pre-existing confusion about this. See https://api.flutter.dev/flutter/material/DropdownButton/value.html. Can you make the docs consistent about when the hint is displayed, and what exactly makes the button enabled/disabled?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've updated the docs to be consistent with what exactly makes a button enabled/disabled.

Copy link
Contributor

@HansMuller HansMuller left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.
This is a now a twofer!

/// The value of the currently selected [DropdownMenuItem].
///
/// If [value] is null and [hint] is non-null, the [hint] widget is
/// displayed as a placeholder for the dropdown button.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... for the dropdown button's value.

/// A placeholder widget that is displayed by the dropdown button.
///
/// If [value] is null, this widget is displayed as a placeholder for
/// the dropdown button. This widget is also displayed if the button
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dropdown button => dropdown button's value

/// displayed in grey and it will not respond to input. A disabled button
/// will display the [disabledHint] widget if it is non-null.
/// will display the [disabledHint] widget if it is non-null. If
/// [disabledHint] is also null but [hint] is non-null, [hint] will instead
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will instead be displayed => will be displayed instead

@shihaohong shihaohong added the c: API break Backwards-incompatible API changes label Oct 22, 2019
@shihaohong shihaohong merged commit 734ddd3 into flutter:master Oct 28, 2019
@shihaohong shihaohong deleted the dropdown-disabled-hint branch October 28, 2019 18:00
Inconnu08 pushed a commit to Inconnu08/flutter that referenced this pull request Nov 26, 2019
…ter#42479)

* Fix DropdownButton disabledHint behavior

* Fix hint behavior when selectedItemBuilder is null

* Improve variable names, some formatting updates

* Create _DropdownMenuItemContainer widget

* Improve API docs to be consistent with hint/disabledHint actual behavior
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Aug 3, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

c: API break Backwards-incompatible API changes f: material design flutter/packages/flutter/material repository. framework flutter/packages/flutter repository. See also f: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Dropdown menu hint changes size of dropdown, and it wraps now. Disabled DropdownButton hint is wrapped by DropdownMenuItem<T> by default

3 participants