DropdownButtonFormField<T> constructor

DropdownButtonFormField<T>({
  1. Key? key,
  2. required List<DropdownMenuItem<T>>? items,
  3. DropdownButtonBuilder? selectedItemBuilder,
  4. T? value,
  5. Widget? hint,
  6. Widget? disabledHint,
  7. required ValueChanged<T?>? onChanged,
  8. VoidCallback? onTap,
  9. int elevation = 8,
  10. TextStyle? style,
  11. Widget? icon,
  12. Color? iconDisabledColor,
  13. Color? iconEnabledColor,
  14. double iconSize = 24.0,
  15. bool isDense = true,
  16. bool isExpanded = false,
  17. double? itemHeight,
  18. Color? focusColor,
  19. FocusNode? focusNode,
  20. bool autofocus = false,
  21. Color? dropdownColor,
  22. InputDecoration? decoration,
  23. FormFieldSetter<T>? onSaved,
  24. FormFieldValidator<T>? validator,
  25. AutovalidateMode? autovalidateMode,
  26. double? menuMaxHeight,
  27. bool? enableFeedback,
  28. AlignmentGeometry alignment = AlignmentDirectional.centerStart,
  29. BorderRadius? borderRadius,
  30. EdgeInsetsGeometry? padding,
})

Creates a DropdownButton widget that is a FormField, wrapped in an InputDecorator.

For a description of the onSaved, validator, or autovalidateMode parameters, see FormField. For the rest (other than decoration), see DropdownButton.

Implementation

DropdownButtonFormField({
  super.key,
  required List<DropdownMenuItem<T>>? items,
  DropdownButtonBuilder? selectedItemBuilder,
  T? value,
  Widget? hint,
  Widget? disabledHint,
  required this.onChanged,
  VoidCallback? onTap,
  int elevation = 8,
  TextStyle? style,
  Widget? icon,
  Color? iconDisabledColor,
  Color? iconEnabledColor,
  double iconSize = 24.0,
  bool isDense = true,
  bool isExpanded = false,
  double? itemHeight,
  Color? focusColor,
  FocusNode? focusNode,
  bool autofocus = false,
  Color? dropdownColor,
  InputDecoration? decoration,
  super.onSaved,
  super.validator,
  AutovalidateMode? autovalidateMode,
  double? menuMaxHeight,
  bool? enableFeedback,
  AlignmentGeometry alignment = AlignmentDirectional.centerStart,
  BorderRadius? borderRadius,
  EdgeInsetsGeometry? padding,
  // When adding new arguments, consider adding similar arguments to
  // DropdownButton.
}) : assert(
       items == null ||
           items.isEmpty ||
           value == null ||
           items.where((DropdownMenuItem<T> item) => item.value == value).length == 1,
       "There should be exactly one item with [DropdownButton]'s value: "
       '$value. \n'
       'Either zero or 2 or more [DropdownMenuItem]s were detected '
       'with the same value',
     ),
     assert(itemHeight == null || itemHeight >= kMinInteractiveDimension),
     decoration = decoration ?? const InputDecoration(),
     super(
       initialValue: value,
       autovalidateMode: autovalidateMode ?? AutovalidateMode.disabled,
       builder: (FormFieldState<T> field) {
         final _DropdownButtonFormFieldState<T> state = field as _DropdownButtonFormFieldState<T>;
         final InputDecoration decorationArg = decoration ?? const InputDecoration();
         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 isDropdownEnabled = onChanged != null && items != null && items.isNotEmpty;
         // If decoration hintText is provided, use it as the default value for both hint and disabledHint.
         final Widget? decorationHint =
             effectiveDecoration.hintText != null ? Text(effectiveDecoration.hintText!) : null;
         final Widget? effectiveHint = hint ?? decorationHint;
         final Widget? effectiveDisabledHint = disabledHint ?? effectiveHint;
         final bool isHintOrDisabledHintAvailable =
             isDropdownEnabled
                 ? effectiveHint != null
                 : effectiveHint != null || effectiveDisabledHint != null;
         final bool isEmpty = !showSelectedItem && !isHintOrDisabledHintAvailable;

         // An unfocusable Focus widget so that this widget can detect if its
         // descendants have focus or not.
         return Focus(
           canRequestFocus: false,
           skipTraversal: true,
           child: Builder(
             builder: (BuildContext context) {
               return DropdownButtonHideUnderline(
                 child: DropdownButton<T>._formField(
                   items: items,
                   selectedItemBuilder: selectedItemBuilder,
                   value: state.value,
                   hint: effectiveHint,
                   disabledHint: effectiveDisabledHint,
                   onChanged: onChanged == null ? null : state.didChange,
                   onTap: onTap,
                   elevation: elevation,
                   style: style,
                   icon: icon,
                   iconDisabledColor: iconDisabledColor,
                   iconEnabledColor: iconEnabledColor,
                   iconSize: iconSize,
                   isDense: isDense,
                   isExpanded: isExpanded,
                   itemHeight: itemHeight,
                   focusColor: focusColor,
                   focusNode: focusNode,
                   autofocus: autofocus,
                   dropdownColor: dropdownColor,
                   menuMaxHeight: menuMaxHeight,
                   enableFeedback: enableFeedback,
                   alignment: alignment,
                   borderRadius: borderRadius,
                   // Clear the decoration hintText because DropdownButton has its own hint logic.
                   inputDecoration: effectiveDecoration.copyWith(
                     errorText: field.errorText,
                     hintText: effectiveDecoration.hintText != null ? '' : null,
                   ),
                   isEmpty: isEmpty,
                   padding: padding,
                 ),
               );
             },
           ),
         );
       },
     );