searchable_dropdown_pro 1.1.0 copy "searchable_dropdown_pro: ^1.1.0" to clipboard
searchable_dropdown_pro: ^1.1.0 copied to clipboard

A highly flexible, production-ready searchable dropdown for Flutter. Supports custom text fields, custom validators, lazy-loaded items, composited overlay positioning, and toggleable search — all with [...]

searchable_dropdown_pro #

pub.dev License: BSD-3-Clause Flutter

A highly flexible, production-ready searchable dropdown for Flutter with zero forced dependencies beyond the Flutter SDK itself.


Features #

  • Bring your own TextField — or use the sensible built-in default.
  • Bring your own validator — standard Flutter form-field API.
  • Toggle search on/offisSearchable: false for a plain dropdown.
  • Custom filter logic — override the default substring match.
  • Custom item tiles — full control over each row.
  • Composited overlay — stays pinned inside SingleChildScrollView.
  • Async / lazy items — pass a new items list and the overlay refreshes.
  • Programmatic control — open, close, clear, or pre-fill via SearchableDropdownController.
  • Full themingSearchableDropdownDecoration covers every visual detail.
  • Null-safe — written for Dart 3 with sound null safety.

Getting started #

Add the dependency to your pubspec.yaml:

dependencies:
  searchable_dropdown_pro: ^1.0.0

Then run:

flutter pub get

Usage #

Minimal #

import 'package:searchable_dropdown_pro/searchable_dropdown_pro.dart';

SearchableDropdownPro<String>(
  items: ['Apple', 'Banana', 'Cherry'],
  displayString: (item) => item,
  onSelected: (item) => print('Selected: $item'),
  hintText: 'Pick a fruit',
)

With a model class #

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

SearchableDropdownPro<Country>(
  items: countries,
  displayString: (c) => c.name,
  onSelected: (c) => _onCountrySelected(c),
  hintText: 'Select country',
)

Non-searchable dropdown #

Pass isSearchable: false and the list is shown as-is without a search input — identical behaviour to a plain DropdownButton but with a composited overlay and full theming.

SearchableDropdownPro<String>(
  isSearchable: false,
  items: ['Small', 'Medium', 'Large'],
  displayString: (s) => s,
  onSelected: (_) {},
  hintText: 'Select size',
)

Bring your own TextField #

Supply fieldBuilder to render any widget as the trigger. The builder receives the managed TextEditingController, FocusNode, and a pre-built suffixIcon so you can embed your own design-system field:

SearchableDropdownPro<String>(
  items: items,
  displayString: (e) => e,
  onSelected: (_) {},
  hintText: 'Search…',
  fieldBuilder: (context, controller, focusNode, suffixIcon) {
    return MyDesignSystemTextField(
      controller: controller,
      focusNode: focusNode,
      suffixIcon: suffixIcon,
      hintText: 'Search…',
    );
  },
)

Bring your own validator #

SearchableDropdownPro<String>(
  items: items,
  displayString: (e) => e,
  onSelected: (_) {},
  hintText: 'Required field',
  validator: (value) {
    if (value == null || value.isEmpty) return 'Please select an option';
    return null;
  },
  autovalidateMode: AutovalidateMode.onUserInteraction,
)

Custom item tiles #

SearchableDropdownPro<Country>(
  items: countries,
  displayString: (c) => c.name,
  onSelected: (_) {},
  hintText: 'Country',
  itemBuilder: (context, country, isSelected, onTap) {
    return ListTile(
      leading: Text(country.flag, style: const TextStyle(fontSize: 24)),
      title: Text(country.name),
      selected: isSelected,
      onTap: onTap,
    );
  },
)

Custom filter #

SearchableDropdownPro<String>(
  items: items,
  displayString: (e) => e,
  onSelected: (_) {},
  hintText: 'Starts-with search',
  filterBuilder: (items, query) =>
      items.where((e) => e.startsWith(query)).toList(),
)

Async / lazy-loaded items #

Just rebuild with a new items list — the overlay refreshes automatically:

SearchableDropdownPro<City>(
  items: _cities,          // starts empty, populated after API call
  displayString: (c) => c.name,
  onSelected: (_) {},
  hintText: 'City',
)

Programmatic control #

final _ctrl = SearchableDropdownController();

@override
void dispose() {
  _ctrl.dispose();
  super.dispose();
}

// Widget
SearchableDropdownPro<String>(
  items: items,
  displayString: (e) => e,
  onSelected: (_) {},
  hintText: 'Pick one',
  controller: _ctrl,
)

// Elsewhere in your code
_ctrl.open();
_ctrl.close();
_ctrl.clear();
_ctrl.setText('Pre-filled value');

Theming #

SearchableDropdownPro<String>(
  items: items,
  displayString: (e) => e,
  onSelected: (_) {},
  hintText: 'Themed',
  decoration: SearchableDropdownDecoration(
    dropdownColor: Colors.grey.shade900,
    dropdownElevation: 8,
    borderRadius: BorderRadius.circular(12),
    itemTextStyle: const TextStyle(color: Colors.white),
    selectedItemColor: Colors.blue.withOpacity(0.2),
    dividerColor: Colors.grey.shade700,
    noMatchText: 'Nothing found 🤷',
    suffixIcon: const Icon(Icons.arrow_drop_down, color: Colors.blue),
  ),
)

API reference #

SearchableDropdownPro<T> #

Parameter Type Default Description
items List<T> required Items to display.
displayString String Function(T) required Converts an item to its label.
onSelected ValueChanged<T> required Called on selection.
hintText String required Placeholder text.
isSearchable bool true Enables typing to filter.
enabled bool true Enables / disables the field.
clearOnOpen bool true Clears field text when opened.
clearAfterSelection bool false Clears field after selection.
maxVisibleItems int 5 Items visible before scrolling.
fieldHeight double 52 Height used to offset the overlay.
selectedItem T? null Highlights the selected item in the list.
filterBuilder List<T> Function(List<T>, String)? null Custom filter logic.
itemBuilder Widget Function(…)? null Custom item tile builder.
fieldBuilder Widget Function(…)? null Custom field widget builder.
validator String? Function(String?)? null Form validator.
autovalidateMode AutovalidateMode? null When to run the validator.
decoration SearchableDropdownDecoration const SearchableDropdownDecoration() Visual configuration.
controller SearchableDropdownController? null Programmatic control.
onChanged ValueChanged<String>? null Text change callback.
onDropdownToggle ValueChanged<bool>? null Open/close callback.
textEditingController TextEditingController? null External text controller.
focusNode FocusNode? null External focus node.

SearchableDropdownController #

Method Description
open() Opens the dropdown overlay.
close() Closes the dropdown overlay.
clear() Clears the text field and selection.
setText(String) Pre-fills the field without triggering onSelected.

SearchableDropdownDecoration #

Property Type Default Description
dropdownColor Color? Theme surface Overlay background.
dropdownElevation double 4 Shadow depth.
borderRadius BorderRadius? 8 Overlay corner radius.
overlayVerticalOffset double 4 Gap between field and overlay.
itemPadding EdgeInsetsGeometry? H:12 V:10 Item tile padding.
itemHeight double? 52 Fixed item tile height.
itemTextStyle TextStyle? bodyMedium Item label style.
noMatchText String 'No match found' Empty-results message.
showDivider bool true Show dividers between items.
dividerColor Color? Theme divider Divider colour.
selectedItemColor Color? null Highlight colour for selected item.
suffixIcon Widget? Arrow icon Custom dropdown arrow.
animateSuffixIcon bool true Rotate arrow on open.

Additional information #

2
likes
140
points
4
downloads

Documentation

Documentation
API reference

Publisher

verified publishermysteriouscoder.com

Weekly Downloads

A highly flexible, production-ready searchable dropdown for Flutter. Supports custom text fields, custom validators, lazy-loaded items, composited overlay positioning, and toggleable search — all with zero required dependencies beyond Flutter itself.

Repository (GitHub)
View/report issues

Topics

#dropdown #searchable #autocomplete #ui #form

License

BSD-3-Clause (license)

Dependencies

flutter

More

Packages that depend on searchable_dropdown_pro