CustomDropdown<T> class

A highly customizable, production-ready generic dropdown widget wrapping Flutter's DropdownMenu.

Features

  • Full Layout Customization: Use itemBuilder to create any item UI
  • Type-Safe Generic Support: Works with any model class via generic type parameter
  • Icon Support: Add prefixIcon, suffixIcon, leadingIcon, or trailingIcon
  • Enable/Disable: Control interaction with enabled property
  • Complete Styling: MenuStyle, border radius, colors, elevation
  • Validation: Display validation messages with validationMessage
  • Search & Filter: Built-in search and filter capabilities

Basic Usage

Simple String Dropdown

CustomDropdown<String>(
  items: ['Apple', 'Banana', 'Orange'],
  itemBuilder: (context, item) => Text(item),
  onSelected: (value) => print('Selected: $value'),
  label: Text('Choose Fruit'),
)

Model Class with Icons

class Country {
  final String name;
  final String flag;
  Country(this.name, this.flag);
}

CustomDropdown<Country>(
  items: [
    Country('USA', '🇺🇸'),
    Country('India', '🇮🇳'),
    Country('Japan', '🇯🇵'),
  ],
  itemBuilder: (context, country) => Row(
    children: [
      Text(country.flag, style: TextStyle(fontSize: 20)),
      SizedBox(width: 10),
      Text(country.name),
    ],
  ),
  prefixIcon: Icon(Icons.flag),
  onSelected: (value) => setState(() => selected = value),
)

With Validation

CustomDropdown<String>(
  items: ['Option 1', 'Option 2'],
  itemBuilder: (context, item) => Text(item),
  onSelected: (value) => setState(() => selected = value),
  validationMessage: selected == null ? 'Please select an option' : null,
)

Custom Styling

CustomDropdown<String>(
  items: ['Light', 'Dark', 'Auto'],
  itemBuilder: (context, item) => Text(item),
  borderRadius: 12,
  menuBackgroundColor: Colors.blue.shade50,
  menuElevation: 8,
  onSelected: (value) => print(value),
)

Advanced Customization

For complete control, use menuStyle for the dropdown panel and dropdownMenuEntries with custom ButtonStyle for individual items.

Reference: https://api.flutter.dev/flutter/material/DropdownMenu-class.html

Inheritance

Constructors

CustomDropdown({Key? key, required Widget itemBuilder(BuildContext, T item), List<T>? items, List<DropdownMenuEntry<T>>? dropdownMenuEntries, T? initialSelection, ValueChanged<T?>? onSelected, bool enabled = true, bool enableFilter = false, bool enableSearch = true, TextEditingController? controller, TextStyle? textStyle, Object? inputDecorationTheme, MenuStyle? menuStyle, Widget? leadingIcon, Widget? trailingIcon, bool showTrailingIcon = true, FocusNode? trailingIconFocusNode, Widget? selectedTrailingIcon, Widget? label, String? hintText, String? helperText, String? errorText, TextInputType? keyboardType, TextAlign textAlign = TextAlign.start, EdgeInsetsGeometry? expandedInsets, FilterCallback<T>? filterCallback, SearchCallback<T>? searchCallback, Offset? alignmentOffset, List<TextInputFormatter>? inputFormatters, DropdownMenuCloseBehavior closeBehavior = DropdownMenuCloseBehavior.all, int? maxLines = 1, TextInputAction? textInputAction, double? cursorHeight, String? restorationId, MenuController? menuController, bool? requestFocusOnTap, Widget selectedBuilder(BuildContext, T?)?, String? validationMessage, TextStyle? validationTextStyle, double? width, double? menuHeight, Widget? prefixIcon, Widget? suffixIcon, double? borderRadius, Color? menuBackgroundColor, double? menuElevation})
const

Properties

alignmentOffset → Offset?
final
borderRadius → double?
final
closeBehavior → DropdownMenuCloseBehavior
final
controller → TextEditingController?
final
cursorHeight → double?
final
final
enabled → bool
final
enableFilter → bool
final
enableSearch → bool
final
errorText → String?
final
expandedInsets → EdgeInsetsGeometry?
final
filterCallback → FilterCallback<T>?
final
hashCode → int
The hash code for this object.
no setterinherited
helperText → String?
final
hintText → String?
final
initialSelection → T?
final
inputDecorationTheme → Object?
final
inputFormatters → List<TextInputFormatter>?
final
itemBuilder → Widget Function(BuildContext, T item)
final
items → List<T>?
final
key → Key?
Controls how one widget replaces another widget in the tree.
finalinherited
keyboardType → TextInputType?
final
label → Widget?
final
leadingIcon → Widget?
final
maxLines → int?
final
final
final
final
final
final
onSelected → ValueChanged<T?>?
final
prefixIcon → Widget?
final
requestFocusOnTap → bool?
final
restorationId → String?
final
runtimeType → Type
A representation of the runtime type of the object.
no setterinherited
searchCallback → SearchCallback<T>?
final
selectedBuilder → Widget Function(BuildContext, T?)?
final
selectedTrailingIcon → Widget?
final
showTrailingIcon → bool
final
suffixIcon → Widget?
final
textAlign → TextAlign
final
textInputAction → TextInputAction?
final
textStyle → TextStyle?
final
trailingIcon → Widget?
final
trailingIconFocusNode → FocusNode?
final
validationMessage → String?
final
validationTextStyle → TextStyle?
final
width → double?
final

Methods

createElement() → StatefulElement
Creates a StatefulElement to manage this widget's location in the tree.
inherited
createState() → State<CustomDropdown<T>>
Creates the mutable state for this widget at a given location in the tree.
override
debugDescribeChildren() → List<DiagnosticsNode>
Returns a list of DiagnosticsNode objects describing this node's children.
inherited
debugFillProperties(DiagnosticPropertiesBuilder properties) → void
Add additional properties associated with the node.
inherited
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
toDiagnosticsNode({String? name, DiagnosticsTreeStyle? style}) → DiagnosticsNode
Returns a debug representation of the object that is used by debugging tools and by DiagnosticsNode.toStringDeep.
inherited
toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) → String
A string representation of this object.
inherited
toStringDeep({String prefixLineOne = '', String? prefixOtherLines, DiagnosticLevel minLevel = DiagnosticLevel.debug, int wrapWidth = 65}) → String
Returns a string representation of this node and its descendants.
inherited
toStringShallow({String joiner = ', ', DiagnosticLevel minLevel = DiagnosticLevel.debug}) → String
Returns a one-line detailed description of the object.
inherited
toStringShort() → String
A short, textual description of this widget.
inherited

Operators

operator ==(Object other) → bool
The equality operator.
inherited