Use decoration hint text as the default value for dropdown button hints (#152474)

## Description

This PR makes `DropdownButtonFormField` hint defaults to the provided inputDecoration hintText.

Because `DropDownButtonFormField` accepts both a `hint` parameter and a `decoration`parameter, one can expect `InputDecoration.hintText` to be valid.

Before this PR, when `InputDecoration.hintText` was specified, it is shown but the vertical position is wrong.
After this PR, when `InputDecoration.hintText` is specified, it is used as the default value for `DropDownButtonFormField.hint` and `DropDownButtonFormField.disabledHint`.

| Before | After |
|--------|--------|
| ![image](https://github.com/user-attachments/assets/a08ff75c-edd4-4e16-9cfa-98ddb349d860) | ![image](https://github.com/user-attachments/assets/55f08bee-8f88-4125-8fae-68e2be724955) |

## Related Issue

Fixes https://github.com/flutter/flutter/issues/111958.

## Tests

Adds 5 tests.
This commit is contained in:
Bruno Leroux 2024-07-31 13:22:26 +02:00 committed by GitHub
parent 0c6b600e76
commit 1a8e57f42e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 197 additions and 129 deletions

View File

@ -1671,45 +1671,43 @@ class DropdownButtonFormField<T> extends FormField<T> {
EdgeInsetsGeometry? padding, EdgeInsetsGeometry? padding,
// When adding new arguments, consider adding similar arguments to // When adding new arguments, consider adding similar arguments to
// DropdownButton. // DropdownButton.
}) : assert(items == null || items.isEmpty || value == null || }) : assert(items == null || items.isEmpty || value == null ||
items.where((DropdownMenuItem<T> item) { items.where((DropdownMenuItem<T> item) => item.value == value).length == 1,
return item.value == value; "There should be exactly one item with [DropdownButton]'s value: "
}).length == 1, '$value. \n'
"There should be exactly one item with [DropdownButton]'s value: " 'Either zero or 2 or more [DropdownMenuItem]s were detected '
'$value. \n' 'with the same value',
'Either zero or 2 or more [DropdownMenuItem]s were detected ' ),
'with the same value', assert(itemHeight == null || itemHeight >= kMinInteractiveDimension),
), decoration = decoration ?? InputDecoration(focusColor: focusColor),
assert(itemHeight == null || itemHeight >= kMinInteractiveDimension), super(
decoration = decoration ?? InputDecoration(focusColor: focusColor), initialValue: value,
super( autovalidateMode: autovalidateMode ?? AutovalidateMode.disabled,
initialValue: value, builder: (FormFieldState<T> field) {
autovalidateMode: autovalidateMode ?? AutovalidateMode.disabled, final _DropdownButtonFormFieldState<T> state = field as _DropdownButtonFormFieldState<T>;
builder: (FormFieldState<T> field) { final InputDecoration decorationArg = decoration ?? InputDecoration(focusColor: focusColor);
final _DropdownButtonFormFieldState<T> state = field as _DropdownButtonFormFieldState<T>; final InputDecoration effectiveDecoration = decorationArg.applyDefaults(
final InputDecoration decorationArg = decoration ?? InputDecoration(focusColor: focusColor); Theme.of(field.context).inputDecorationTheme,
final InputDecoration effectiveDecoration = decorationArg.applyDefaults( );
Theme.of(field.context).inputDecorationTheme,
);
final bool showSelectedItem = items != null && items.where((DropdownMenuItem<T> item) => item.value == state.value).isNotEmpty; final bool showSelectedItem = items != null && items.where((DropdownMenuItem<T> item) => item.value == state.value).isNotEmpty;
bool isHintOrDisabledHintAvailable() { final bool isDropdownEnabled = onChanged != null && items != null && items.isNotEmpty;
final bool isDropdownDisabled = onChanged == null || (items == null || items.isEmpty); // If decoration hintText is provided, use it as the default value for both hint and disabledHint.
if (isDropdownDisabled) { final Widget? decorationHint = effectiveDecoration.hintText != null ? Text(effectiveDecoration.hintText!) : null;
return hint != null || disabledHint != null; final Widget? effectiveHint = hint ?? decorationHint;
} else { final Widget? effectiveDisabledHint = disabledHint ?? effectiveHint;
return hint != null; final bool isHintOrDisabledHintAvailable = isDropdownEnabled
} ? effectiveHint != null
} : effectiveHint != null || effectiveDisabledHint != null;
final bool isEmpty = !showSelectedItem && !isHintOrDisabledHintAvailable(); final bool isEmpty = !showSelectedItem && !isHintOrDisabledHintAvailable;
final bool hasError = effectiveDecoration.errorText != null; final bool hasError = effectiveDecoration.errorText != null;
// An unfocusable Focus widget so that this widget can detect if its // An unfocusable Focus widget so that this widget can detect if its
// descendants have focus or not. // descendants have focus or not.
return Focus( return Focus(
canRequestFocus: false, canRequestFocus: false,
skipTraversal: true, skipTraversal: true,
child: Builder(builder: (BuildContext context) { child: Builder(builder: (BuildContext context) {
final bool isFocused = Focus.of(context).hasFocus; final bool isFocused = Focus.of(context).hasFocus;
InputBorder? resolveInputBorder() { InputBorder? resolveInputBorder() {
if (hasError) { if (hasError) {
@ -1737,42 +1735,46 @@ class DropdownButtonFormField<T> extends FormField<T> {
return null; return null;
} }
return DropdownButtonHideUnderline( return DropdownButtonHideUnderline(
child: DropdownButton<T>._formField( child: DropdownButton<T>._formField(
items: items, items: items,
selectedItemBuilder: selectedItemBuilder, selectedItemBuilder: selectedItemBuilder,
value: state.value, value: state.value,
hint: hint, hint: effectiveHint,
disabledHint: disabledHint, disabledHint: effectiveDisabledHint,
onChanged: onChanged == null ? null : state.didChange, onChanged: onChanged == null ? null : state.didChange,
onTap: onTap, onTap: onTap,
elevation: elevation, elevation: elevation,
style: style, style: style,
icon: icon, icon: icon,
iconDisabledColor: iconDisabledColor, iconDisabledColor: iconDisabledColor,
iconEnabledColor: iconEnabledColor, iconEnabledColor: iconEnabledColor,
iconSize: iconSize, iconSize: iconSize,
isDense: isDense, isDense: isDense,
isExpanded: isExpanded, isExpanded: isExpanded,
itemHeight: itemHeight, itemHeight: itemHeight,
focusColor: focusColor, focusColor: focusColor,
focusNode: focusNode, focusNode: focusNode,
autofocus: autofocus, autofocus: autofocus,
dropdownColor: dropdownColor, dropdownColor: dropdownColor,
menuMaxHeight: menuMaxHeight, menuMaxHeight: menuMaxHeight,
enableFeedback: enableFeedback, enableFeedback: enableFeedback,
alignment: alignment, alignment: alignment,
borderRadius: borderRadius ?? effectiveBorderRadius(), borderRadius: borderRadius ?? effectiveBorderRadius(),
inputDecoration: effectiveDecoration.copyWith(errorText: field.errorText), // Clear the decoration hintText because DropdownButton has its own hint logic.
isEmpty: isEmpty, inputDecoration: effectiveDecoration.copyWith(
isFocused: isFocused, errorText: field.errorText,
padding: padding, hintText: effectiveDecoration.hintText != null ? '' : null,
), ),
); isEmpty: isEmpty,
}), isFocused: isFocused,
); padding: padding,
}, ),
); );
}),
);
},
);
/// {@macro flutter.material.dropdownButton.onChanged} /// {@macro flutter.material.dropdownButton.onChanged}
final ValueChanged<T?>? onChanged; final ValueChanged<T?>? onChanged;

View File

@ -69,6 +69,7 @@ Widget buildDropdown({
Color? dropdownColor, Color? dropdownColor,
double? menuMaxHeight, double? menuMaxHeight,
EdgeInsetsGeometry? padding, EdgeInsetsGeometry? padding,
InputDecoration? decoration,
}) { }) {
final List<DropdownMenuItem<String>>? listItems = items?.map<DropdownMenuItem<String>>((String item) { final List<DropdownMenuItem<String>>? listItems = items?.map<DropdownMenuItem<String>>((String item) {
return DropdownMenuItem<String>( return DropdownMenuItem<String>(
@ -104,6 +105,7 @@ Widget buildDropdown({
alignment: alignment, alignment: alignment,
menuMaxHeight: menuMaxHeight, menuMaxHeight: menuMaxHeight,
padding: padding, padding: padding,
decoration: decoration,
), ),
); );
} }
@ -165,6 +167,7 @@ Widget buildFrame({
EdgeInsetsGeometry? padding, EdgeInsetsGeometry? padding,
Alignment dropdownAlignment = Alignment.center, Alignment dropdownAlignment = Alignment.center,
bool? useMaterial3, bool? useMaterial3,
InputDecoration? decoration,
}) { }) {
return Theme( return Theme(
data: ThemeData(useMaterial3: useMaterial3), data: ThemeData(useMaterial3: useMaterial3),
@ -201,6 +204,7 @@ Widget buildFrame({
alignment: alignment, alignment: alignment,
menuMaxHeight: menuMaxHeight, menuMaxHeight: menuMaxHeight,
padding: padding, padding: padding,
decoration: decoration,
), ),
), ),
), ),
@ -3741,50 +3745,50 @@ void main() {
alignment: AlignmentDirectional.centerStart, alignment: AlignmentDirectional.centerStart,
isExpanded: false, isExpanded: false,
)); ));
expect(tester.getTopLeft(find.text(hintText,skipOffstage: false)).dx, 348.0); expect(tester.getTopLeft(find.text(hintText, skipOffstage: false)).dx, 348.0);
expect(tester.getTopLeft(find.text(hintText,skipOffstage: false)).dy, 292.0); expect(tester.getTopLeft(find.text(hintText, skipOffstage: false)).dy, 292.0);
// AlignmentDirectional.topStart // AlignmentDirectional.topStart
await tester.pumpWidget(buildDropdownWithHint( await tester.pumpWidget(buildDropdownWithHint(
alignment: AlignmentDirectional.topStart, alignment: AlignmentDirectional.topStart,
isExpanded: false, isExpanded: false,
)); ));
expect(tester.getTopLeft(find.text(hintText,skipOffstage: false)).dx, 348.0); expect(tester.getTopLeft(find.text(hintText, skipOffstage: false)).dx, 348.0);
expect(tester.getTopLeft(find.text(hintText,skipOffstage: false)).dy, 250.0); expect(tester.getTopLeft(find.text(hintText, skipOffstage: false)).dy, 250.0);
// AlignmentDirectional.bottomStart // AlignmentDirectional.bottomStart
await tester.pumpWidget(buildDropdownWithHint( await tester.pumpWidget(buildDropdownWithHint(
alignment: AlignmentDirectional.bottomStart, alignment: AlignmentDirectional.bottomStart,
isExpanded: false, isExpanded: false,
)); ));
expect(tester.getBottomLeft(find.text(hintText,skipOffstage: false)).dx, 348.0); expect(tester.getBottomLeft(find.text(hintText, skipOffstage: false)).dx, 348.0);
expect(tester.getBottomLeft(find.text(hintText,skipOffstage: false)).dy, 350.0); expect(tester.getBottomLeft(find.text(hintText, skipOffstage: false)).dy, 350.0);
// AlignmentDirectional.center // AlignmentDirectional.center
await tester.pumpWidget(buildDropdownWithHint( await tester.pumpWidget(buildDropdownWithHint(
alignment: AlignmentDirectional.center, alignment: AlignmentDirectional.center,
isExpanded: false, isExpanded: false,
)); ));
expect(tester.getCenter(find.text(hintText,skipOffstage: false)).dx, 388.0); expect(tester.getCenter(find.text(hintText, skipOffstage: false)).dx, 388.0);
expect(tester.getCenter(find.text(hintText,skipOffstage: false)).dy, 300.0); expect(tester.getCenter(find.text(hintText, skipOffstage: false)).dy, 300.0);
// AlignmentDirectional.topEnd // AlignmentDirectional.topEnd
await tester.pumpWidget(buildDropdownWithHint( await tester.pumpWidget(buildDropdownWithHint(
alignment: AlignmentDirectional.topEnd, alignment: AlignmentDirectional.topEnd,
isExpanded: false, isExpanded: false,
)); ));
expect(tester.getTopRight(find.text(hintText,skipOffstage: false)).dx, 428.0); expect(tester.getTopRight(find.text(hintText, skipOffstage: false)).dx, 428.0);
expect(tester.getTopRight(find.text(hintText,skipOffstage: false)).dy, 250.0); expect(tester.getTopRight(find.text(hintText, skipOffstage: false)).dy, 250.0);
// AlignmentDirectional.centerEnd // AlignmentDirectional.centerEnd
await tester.pumpWidget(buildDropdownWithHint( await tester.pumpWidget(buildDropdownWithHint(
alignment: AlignmentDirectional.centerEnd, alignment: AlignmentDirectional.centerEnd,
isExpanded: false, isExpanded: false,
)); ));
expect(tester.getTopRight(find.text(hintText,skipOffstage: false)).dx, 428.0); expect(tester.getTopRight(find.text(hintText, skipOffstage: false)).dx, 428.0);
expect(tester.getTopRight(find.text(hintText,skipOffstage: false)).dy, 292.0); expect(tester.getTopRight(find.text(hintText, skipOffstage: false)).dy, 292.0);
// AlignmentDirectional.bottomEnd // AlignmentDirectional.bottomEnd
await tester.pumpWidget(buildDropdownWithHint( await tester.pumpWidget(buildDropdownWithHint(
alignment: AlignmentDirectional.bottomEnd, alignment: AlignmentDirectional.bottomEnd,
isExpanded: false, isExpanded: false,
)); ));
expect(tester.getTopRight(find.text(hintText,skipOffstage: false)).dx, 428.0); expect(tester.getTopRight(find.text(hintText, skipOffstage: false)).dx, 428.0);
expect(tester.getTopRight(find.text(hintText,skipOffstage: false)).dy, 334.0); expect(tester.getTopRight(find.text(hintText, skipOffstage: false)).dy, 334.0);
// DropdownButton with `isExpanded: true` // DropdownButton with `isExpanded: true`
// AlignmentDirectional.centerStart (default) // AlignmentDirectional.centerStart (default)
@ -3792,50 +3796,50 @@ void main() {
alignment: AlignmentDirectional.centerStart, alignment: AlignmentDirectional.centerStart,
isExpanded: true, isExpanded: true,
)); ));
expect(tester.getTopLeft(find.text(hintText,skipOffstage: false)).dx, 0.0); expect(tester.getTopLeft(find.text(hintText, skipOffstage: false)).dx, 0.0);
expect(tester.getTopLeft(find.text(hintText,skipOffstage: false)).dy, 292.0); expect(tester.getTopLeft(find.text(hintText, skipOffstage: false)).dy, 292.0);
// AlignmentDirectional.topStart // AlignmentDirectional.topStart
await tester.pumpWidget(buildDropdownWithHint( await tester.pumpWidget(buildDropdownWithHint(
alignment: AlignmentDirectional.topStart, alignment: AlignmentDirectional.topStart,
isExpanded: true, isExpanded: true,
)); ));
expect(tester.getTopLeft(find.text(hintText,skipOffstage: false)).dx, 0.0); expect(tester.getTopLeft(find.text(hintText, skipOffstage: false)).dx, 0.0);
expect(tester.getTopLeft(find.text(hintText,skipOffstage: false)).dy, 250.0); expect(tester.getTopLeft(find.text(hintText, skipOffstage: false)).dy, 250.0);
// AlignmentDirectional.bottomStart // AlignmentDirectional.bottomStart
await tester.pumpWidget(buildDropdownWithHint( await tester.pumpWidget(buildDropdownWithHint(
alignment: AlignmentDirectional.bottomStart, alignment: AlignmentDirectional.bottomStart,
isExpanded: true, isExpanded: true,
)); ));
expect(tester.getBottomLeft(find.text(hintText,skipOffstage: false)).dx, 0.0); expect(tester.getBottomLeft(find.text(hintText, skipOffstage: false)).dx, 0.0);
expect(tester.getBottomLeft(find.text(hintText,skipOffstage: false)).dy, 350.0); expect(tester.getBottomLeft(find.text(hintText, skipOffstage: false)).dy, 350.0);
// AlignmentDirectional.center // AlignmentDirectional.center
await tester.pumpWidget(buildDropdownWithHint( await tester.pumpWidget(buildDropdownWithHint(
alignment: AlignmentDirectional.center, alignment: AlignmentDirectional.center,
isExpanded: true, isExpanded: true,
)); ));
expect(tester.getCenter(find.text(hintText,skipOffstage: false)).dx, 388.0); expect(tester.getCenter(find.text(hintText, skipOffstage: false)).dx, 388.0);
expect(tester.getCenter(find.text(hintText,skipOffstage: false)).dy, 300.0); expect(tester.getCenter(find.text(hintText, skipOffstage: false)).dy, 300.0);
// AlignmentDirectional.topEnd // AlignmentDirectional.topEnd
await tester.pumpWidget(buildDropdownWithHint( await tester.pumpWidget(buildDropdownWithHint(
alignment: AlignmentDirectional.topEnd, alignment: AlignmentDirectional.topEnd,
isExpanded: true, isExpanded: true,
)); ));
expect(tester.getTopRight(find.text(hintText,skipOffstage: false)).dx, 776.0); expect(tester.getTopRight(find.text(hintText, skipOffstage: false)).dx, 776.0);
expect(tester.getTopRight(find.text(hintText,skipOffstage: false)).dy, 250.0); expect(tester.getTopRight(find.text(hintText, skipOffstage: false)).dy, 250.0);
// AlignmentDirectional.centerEnd // AlignmentDirectional.centerEnd
await tester.pumpWidget(buildDropdownWithHint( await tester.pumpWidget(buildDropdownWithHint(
alignment: AlignmentDirectional.centerEnd, alignment: AlignmentDirectional.centerEnd,
isExpanded: true, isExpanded: true,
)); ));
expect(tester.getTopRight(find.text(hintText,skipOffstage: false)).dx, 776.0); expect(tester.getTopRight(find.text(hintText, skipOffstage: false)).dx, 776.0);
expect(tester.getTopRight(find.text(hintText,skipOffstage: false)).dy, 292.0); expect(tester.getTopRight(find.text(hintText, skipOffstage: false)).dy, 292.0);
// AlignmentDirectional.bottomEnd // AlignmentDirectional.bottomEnd
await tester.pumpWidget(buildDropdownWithHint( await tester.pumpWidget(buildDropdownWithHint(
alignment: AlignmentDirectional.bottomEnd, alignment: AlignmentDirectional.bottomEnd,
isExpanded: true, isExpanded: true,
)); ));
expect(tester.getBottomRight(find.text(hintText,skipOffstage: false)).dx, 776.0); expect(tester.getBottomRight(find.text(hintText, skipOffstage: false)).dx, 776.0);
expect(tester.getBottomRight(find.text(hintText,skipOffstage: false)).dy, 350.0); expect(tester.getBottomRight(find.text(hintText, skipOffstage: false)).dy, 350.0);
}); });
testWidgets('DropdownButton hint alignment with selectedItemBuilder', (WidgetTester tester) async { testWidgets('DropdownButton hint alignment with selectedItemBuilder', (WidgetTester tester) async {
@ -3847,56 +3851,56 @@ void main() {
isExpanded: false, isExpanded: false,
enableSelectedItemBuilder: true, enableSelectedItemBuilder: true,
)); ));
expect(tester.getTopLeft(find.text(hintText,skipOffstage: false)).dx, 348.0); expect(tester.getTopLeft(find.text(hintText, skipOffstage: false)).dx, 348.0);
expect(tester.getTopLeft(find.text(hintText,skipOffstage: false)).dy, 292.0); expect(tester.getTopLeft(find.text(hintText, skipOffstage: false)).dy, 292.0);
// AlignmentDirectional.topStart // AlignmentDirectional.topStart
await tester.pumpWidget(buildDropdownWithHint( await tester.pumpWidget(buildDropdownWithHint(
alignment: AlignmentDirectional.topStart, alignment: AlignmentDirectional.topStart,
isExpanded: false, isExpanded: false,
enableSelectedItemBuilder: true, enableSelectedItemBuilder: true,
)); ));
expect(tester.getTopLeft(find.text(hintText,skipOffstage: false)).dx, 348.0); expect(tester.getTopLeft(find.text(hintText, skipOffstage: false)).dx, 348.0);
expect(tester.getTopLeft(find.text(hintText,skipOffstage: false)).dy, 250.0); expect(tester.getTopLeft(find.text(hintText, skipOffstage: false)).dy, 250.0);
// AlignmentDirectional.bottomStart // AlignmentDirectional.bottomStart
await tester.pumpWidget(buildDropdownWithHint( await tester.pumpWidget(buildDropdownWithHint(
alignment: AlignmentDirectional.bottomStart, alignment: AlignmentDirectional.bottomStart,
isExpanded: false, isExpanded: false,
enableSelectedItemBuilder: true, enableSelectedItemBuilder: true,
)); ));
expect(tester.getBottomLeft(find.text(hintText,skipOffstage: false)).dx, 348.0); expect(tester.getBottomLeft(find.text(hintText, skipOffstage: false)).dx, 348.0);
expect(tester.getBottomLeft(find.text(hintText,skipOffstage: false)).dy, 350.0); expect(tester.getBottomLeft(find.text(hintText, skipOffstage: false)).dy, 350.0);
// AlignmentDirectional.center // AlignmentDirectional.center
await tester.pumpWidget(buildDropdownWithHint( await tester.pumpWidget(buildDropdownWithHint(
alignment: AlignmentDirectional.center, alignment: AlignmentDirectional.center,
isExpanded: false, isExpanded: false,
enableSelectedItemBuilder: true, enableSelectedItemBuilder: true,
)); ));
expect(tester.getCenter(find.text(hintText,skipOffstage: false)).dx, 388.0); expect(tester.getCenter(find.text(hintText, skipOffstage: false)).dx, 388.0);
expect(tester.getCenter(find.text(hintText,skipOffstage: false)).dy, 300.0); expect(tester.getCenter(find.text(hintText, skipOffstage: false)).dy, 300.0);
// AlignmentDirectional.topEnd // AlignmentDirectional.topEnd
await tester.pumpWidget(buildDropdownWithHint( await tester.pumpWidget(buildDropdownWithHint(
alignment: AlignmentDirectional.topEnd, alignment: AlignmentDirectional.topEnd,
isExpanded: false, isExpanded: false,
enableSelectedItemBuilder: true, enableSelectedItemBuilder: true,
)); ));
expect(tester.getTopRight(find.text(hintText,skipOffstage: false)).dx, 428.0); expect(tester.getTopRight(find.text(hintText, skipOffstage: false)).dx, 428.0);
expect(tester.getTopRight(find.text(hintText,skipOffstage: false)).dy, 250.0); expect(tester.getTopRight(find.text(hintText, skipOffstage: false)).dy, 250.0);
// AlignmentDirectional.centerEnd // AlignmentDirectional.centerEnd
await tester.pumpWidget(buildDropdownWithHint( await tester.pumpWidget(buildDropdownWithHint(
alignment: AlignmentDirectional.centerEnd, alignment: AlignmentDirectional.centerEnd,
isExpanded: false, isExpanded: false,
enableSelectedItemBuilder: true, enableSelectedItemBuilder: true,
)); ));
expect(tester.getTopRight(find.text(hintText,skipOffstage: false)).dx, 428.0); expect(tester.getTopRight(find.text(hintText, skipOffstage: false)).dx, 428.0);
expect(tester.getTopRight(find.text(hintText,skipOffstage: false)).dy, 292.0); expect(tester.getTopRight(find.text(hintText, skipOffstage: false)).dy, 292.0);
// AlignmentDirectional.bottomEnd // AlignmentDirectional.bottomEnd
await tester.pumpWidget(buildDropdownWithHint( await tester.pumpWidget(buildDropdownWithHint(
alignment: AlignmentDirectional.bottomEnd, alignment: AlignmentDirectional.bottomEnd,
isExpanded: false, isExpanded: false,
enableSelectedItemBuilder: true, enableSelectedItemBuilder: true,
)); ));
expect(tester.getTopRight(find.text(hintText,skipOffstage: false)).dx, 428.0); expect(tester.getTopRight(find.text(hintText, skipOffstage: false)).dx, 428.0);
expect(tester.getTopRight(find.text(hintText,skipOffstage: false)).dy, 334.0); expect(tester.getTopRight(find.text(hintText, skipOffstage: false)).dy, 334.0);
// DropdownButton with `isExpanded: true` // DropdownButton with `isExpanded: true`
// AlignmentDirectional.centerStart (default) // AlignmentDirectional.centerStart (default)
@ -3905,56 +3909,118 @@ void main() {
isExpanded: true, isExpanded: true,
enableSelectedItemBuilder: true, enableSelectedItemBuilder: true,
)); ));
expect(tester.getTopLeft(find.text(hintText,skipOffstage: false)).dx, 0.0); expect(tester.getTopLeft(find.text(hintText, skipOffstage: false)).dx, 0.0);
expect(tester.getTopLeft(find.text(hintText,skipOffstage: false)).dy, 292.0); expect(tester.getTopLeft(find.text(hintText, skipOffstage: false)).dy, 292.0);
// AlignmentDirectional.topStart // AlignmentDirectional.topStart
await tester.pumpWidget(buildDropdownWithHint( await tester.pumpWidget(buildDropdownWithHint(
alignment: AlignmentDirectional.topStart, alignment: AlignmentDirectional.topStart,
isExpanded: true, isExpanded: true,
enableSelectedItemBuilder: true, enableSelectedItemBuilder: true,
)); ));
expect(tester.getTopLeft(find.text(hintText,skipOffstage: false)).dx, 0.0); expect(tester.getTopLeft(find.text(hintText, skipOffstage: false)).dx, 0.0);
expect(tester.getTopLeft(find.text(hintText,skipOffstage: false)).dy, 250.0); expect(tester.getTopLeft(find.text(hintText, skipOffstage: false)).dy, 250.0);
// AlignmentDirectional.bottomStart // AlignmentDirectional.bottomStart
await tester.pumpWidget(buildDropdownWithHint( await tester.pumpWidget(buildDropdownWithHint(
alignment: AlignmentDirectional.bottomStart, alignment: AlignmentDirectional.bottomStart,
isExpanded: true, isExpanded: true,
enableSelectedItemBuilder: true, enableSelectedItemBuilder: true,
)); ));
expect(tester.getBottomLeft(find.text(hintText,skipOffstage: false)).dx, 0.0); expect(tester.getBottomLeft(find.text(hintText, skipOffstage: false)).dx, 0.0);
expect(tester.getBottomLeft(find.text(hintText,skipOffstage: false)).dy, 350.0); expect(tester.getBottomLeft(find.text(hintText, skipOffstage: false)).dy, 350.0);
// AlignmentDirectional.center // AlignmentDirectional.center
await tester.pumpWidget(buildDropdownWithHint( await tester.pumpWidget(buildDropdownWithHint(
alignment: AlignmentDirectional.center, alignment: AlignmentDirectional.center,
isExpanded: true, isExpanded: true,
enableSelectedItemBuilder: true, enableSelectedItemBuilder: true,
)); ));
expect(tester.getCenter(find.text(hintText,skipOffstage: false)).dx, 388.0); expect(tester.getCenter(find.text(hintText, skipOffstage: false)).dx, 388.0);
expect(tester.getCenter(find.text(hintText,skipOffstage: false)).dy, 300.0); expect(tester.getCenter(find.text(hintText, skipOffstage: false)).dy, 300.0);
// AlignmentDirectional.topEnd // AlignmentDirectional.topEnd
await tester.pumpWidget(buildDropdownWithHint( await tester.pumpWidget(buildDropdownWithHint(
alignment: AlignmentDirectional.topEnd, alignment: AlignmentDirectional.topEnd,
isExpanded: true, isExpanded: true,
enableSelectedItemBuilder: true, enableSelectedItemBuilder: true,
)); ));
expect(tester.getTopRight(find.text(hintText,skipOffstage: false)).dx, 776.0); expect(tester.getTopRight(find.text(hintText, skipOffstage: false)).dx, 776.0);
expect(tester.getTopRight(find.text(hintText,skipOffstage: false)).dy, 250.0); expect(tester.getTopRight(find.text(hintText, skipOffstage: false)).dy, 250.0);
// AlignmentDirectional.centerEnd // AlignmentDirectional.centerEnd
await tester.pumpWidget(buildDropdownWithHint( await tester.pumpWidget(buildDropdownWithHint(
alignment: AlignmentDirectional.centerEnd, alignment: AlignmentDirectional.centerEnd,
isExpanded: true, isExpanded: true,
enableSelectedItemBuilder: true, enableSelectedItemBuilder: true,
)); ));
expect(tester.getTopRight(find.text(hintText,skipOffstage: false)).dx, 776.0); expect(tester.getTopRight(find.text(hintText, skipOffstage: false)).dx, 776.0);
expect(tester.getTopRight(find.text(hintText,skipOffstage: false)).dy, 292.0); expect(tester.getTopRight(find.text(hintText, skipOffstage: false)).dy, 292.0);
// AlignmentDirectional.bottomEnd // AlignmentDirectional.bottomEnd
await tester.pumpWidget(buildDropdownWithHint( await tester.pumpWidget(buildDropdownWithHint(
alignment: AlignmentDirectional.bottomEnd, alignment: AlignmentDirectional.bottomEnd,
isExpanded: true, isExpanded: true,
enableSelectedItemBuilder: true, enableSelectedItemBuilder: true,
)); ));
expect(tester.getBottomRight(find.text(hintText,skipOffstage: false)).dx, 776.0); expect(tester.getBottomRight(find.text(hintText, skipOffstage: false)).dx, 776.0);
expect(tester.getBottomRight(find.text(hintText,skipOffstage: false)).dy, 350.0); expect(tester.getBottomRight(find.text(hintText, skipOffstage: false)).dy, 350.0);
});
group('DropdownButtonFormField decoration hintText', () {
const String decorationHintText = 'Decoration Hint text';
const String hintText = 'Hint text';
const String disabledHintText = 'Disabled Hint text';
testWidgets('is the fallback value for DropdownButtonFormField.hint', (WidgetTester tester) async {
await tester.pumpWidget(buildFrame(
isFormField: true,
onChanged: (String? newValue) {},
decoration: const InputDecoration(hintText: decorationHintText),
));
expect(find.text(decorationHintText, skipOffstage: false), findsOne);
});
testWidgets('does not override DropdownButtonFormField.hint', (WidgetTester tester) async {
await tester.pumpWidget(buildFrame(
hint: const Text(hintText),
isFormField: true,
onChanged: (String? newValue) {},
decoration: const InputDecoration(hintText: decorationHintText),
));
expect(find.text(hintText, skipOffstage: false), findsOne);
expect(find.text(decorationHintText, skipOffstage: false), findsNothing);
});
testWidgets('is the fallback value for DropdownButtonFormField.disabledHint', (WidgetTester tester) async {
// The Dropdown is disabled because onChanged is not defined.
await tester.pumpWidget(buildFrame(
isFormField: true,
decoration: const InputDecoration(hintText: decorationHintText),
));
expect(find.text(decorationHintText, skipOffstage: false), findsOne);
});
testWidgets('does not override DropdownButtonFormField.disabledHint', (WidgetTester tester) async {
// The Dropdown is disabled because onChanged is not defined.
await tester.pumpWidget(buildFrame(
disabledHint: const Text(disabledHintText),
isFormField: true,
decoration: const InputDecoration(hintText: decorationHintText),
));
expect(find.text(disabledHintText, skipOffstage: false), findsOne);
expect(find.text(decorationHintText, skipOffstage: false), findsNothing);
});
testWidgets('is not used for disabledHint if DropdownButtonFormField.hint is provided', (WidgetTester tester) async {
// The Dropdown is disabled because onChanged is not defined.
await tester.pumpWidget(buildFrame(
hint: const Text(hintText),
isFormField: true,
decoration: const InputDecoration(hintText: decorationHintText),
));
expect(find.text(hintText, skipOffstage: false), findsOne);
expect(find.text(decorationHintText, skipOffstage: false), findsNothing);
});
}); });
testWidgets('BorderRadius property clips dropdown button and dropdown menu', (WidgetTester tester) async { testWidgets('BorderRadius property clips dropdown button and dropdown menu', (WidgetTester tester) async {