Flutter Easy Dropdown

Flutter pub package likes popularity pub points License: MIT

A powerful, customizable, and elegant searchable dropdown package for Flutter developers. Supports Single Selection, Multi-Selection with Chips, Online Asynchronous Search, Zero-Dependency Native Pagination (Infinite Scroll), Material 3 Design, and multiple presentation modes (Dialog, BottomSheet, and Menu).


Dropdown search demo


✨ Features

  • 🎯 Single & Multi-Selection Modes: Choose single items or select multiple items with interactive chips and checkbox controls.
  • ⚑ Zero-Dependency Native Pagination: Infinite scrolling and lazy loading (onLoadMore) without outdated external bloc dependencies.
  • 🌐 Async & Online API Search: Built-in support for online APIs, debounced search (searchDelay), and custom loading/error states.
  • 🎨 Material 3 Ready: Modern UI styling, animated trailing chevrons, rounded borders, and dynamic dark/light theme support.
  • πŸ“± 3 Presentation Modes:
    • Mode.dialog: Centered modal dialog with custom max width & shape.
    • Mode.bottomSheet: Modal bottom sheet with drag handle and keyboard avoidance.
    • Mode.menu: Anchor-positioned dropdown popup menu.
  • πŸ” Search & Favorite Chips: Built-in search bar with clear button, plus favorite/frequent item chips for fast selection.
  • πŸ“ Form Integration: Direct support for Flutter Form and validator.
  • πŸ•ΉοΈ Programmatic Control: Open, select, or clear items via GlobalKey<DropdownSearchState<T>>.

πŸ“Έ Screenshots

Dialog Mode Search and Clear
Custom Items Menu Mode

πŸ“¦ Installation

Add flutter_easy_dropdown to your pubspec.yaml:

dependencies:
  flutter_easy_dropdown: ^2.0.0

Then run:

flutter pub get

πŸš€ Quick Start

1. Basic Single Selection Dropdown

import 'package:flutter/material.dart';
import 'package:flutter_easy_dropdown/flutter_easy_dropdown.dart';

DropdownSearch<String>(
  items: const ["United States", "Canada", "United Kingdom", "Germany", "France"],
  selectedItem: "United States",
  label: "Country",
  hint: "Select a country",
  showSearchBox: true,
  showClearButton: true,
  onChanged: (String? value) {
    print("Selected country: $value");
  },
)

2. Multi-Selection Dropdown with Chips

DropdownSearch<String>.multiSelection(
  items: const ["Dart", "Flutter", "Kotlin", "Swift", "TypeScript", "Python", "Rust"],
  selectedItems: const ["Dart", "Flutter"],
  label: "Technologies",
  hint: "Select skills",
  showSearchBox: true,
  showClearButton: true,
  onChanged: (List<String> items) {
    print("Selected skills: $items");
  },
)

3. Online API Search with Debouncing (Async)

DropdownSearch<UserModel>(
  label: "User Account",
  hint: "Search users by name...",
  showSearchBox: true,
  isFilteredOnline: true,
  searchDelay: const Duration(milliseconds: 400),
  asyncItems: (String filter) async {
    final response = await Dio().get(
      "https://jsonplaceholder.typicode.com/users",
    );
    final users = (response.data as List)
        .map((e) => UserModel.fromJson(e))
        .toList();
    
    if (filter.isEmpty) return users;
    return users.where((u) => u.name.toLowerCase().contains(filter.toLowerCase())).toList();
  },
  itemAsString: (UserModel user) => user.name,
  compareFn: (u1, u2) => u1.id == u2?.id,
  popupItemBuilder: (context, user, isSelected) {
    return ListTile(
      leading: CircleAvatar(child: Text(user.name[0])),
      title: Text(user.name),
      subtitle: Text(user.email),
      selected: isSelected,
    );
  },
  onChanged: (UserModel? user) {
    print("Selected user: ${user?.name}");
  },
)

4. Native Infinite Pagination (Load More)

DropdownSearch<String>(
  label: "Paginated Records",
  hint: "Scroll down to load more",
  showSearchBox: true,
  onLoadMore: (String filter, int offset) async {
    // Fetch next page based on offset
    return await fetchDatabaseRecords(filter: filter, offset: offset, limit: 15);
  },
  onChanged: (String? item) {
    print("Selected: $item");
  },
)

5. Presentation Modes (BottomSheet & Menu)

// BottomSheet Mode with Favorite Chips
DropdownSearch<String>(
  mode: Mode.bottomSheet,
  items: const ["New York", "London", "Tokyo", "Paris", "Berlin"],
  showSearchBox: true,
  showFavoriteItems: true,
  favoriteItems: (items) => ["New York", "London", "Tokyo"],
  label: "City Destination",
  hint: "Choose city",
  onChanged: print,
)

// Popup Menu Mode
DropdownSearch<String>(
  mode: Mode.menu,
  items: const ["Light", "Dark", "System Default"],
  label: "Theme",
  onChanged: print,
)

6. Form Validation

DropdownSearch<String>(
  items: const ["Admin", "Editor", "Viewer"],
  label: "User Role *",
  validator: (String? item) {
    if (item == null || item.isEmpty) {
      return "Please select a role";
    }
    return null;
  },
  onChanged: print,
)

7. Programmatic Control

final dropdownKey = GlobalKey<DropdownSearchState<String>>();

// In widget:
DropdownSearch<String>(
  key: dropdownKey,
  items: const ["Option A", "Option B", "Option C"],
  onChanged: print,
)

// In code:
dropdownKey.currentState?.openDropDownSearch();   // Opens popup programmatically
dropdownKey.currentState?.changeSelectedItem("Option B"); // Changes selection
dropdownKey.currentState?.clear();                // Clears selection

πŸ› οΈ Key Properties Reference

Property Type Description
items List<T>? Offline list of items.
selectedItem T? Selected item in single selection mode.
selectedItems List<T> Selected items in multi-selection mode (.multiSelection).
asyncItems / onFind Future<List<T>> Function(String) Online API function to fetch items by query.
onLoadMore Future<List<T>> Function(String, int) Callback for infinite scrolling pagination.
mode Mode Presentation mode (Mode.dialog, Mode.bottomSheet, Mode.menu).
showSearchBox bool Whether to display the search box inside popup (default: false).
showClearButton bool Whether to show the clear button (default: false).
searchDelay Duration? Debounce delay before filtering search (default: 300ms).
itemAsString String Function(T)? Custom string serializer for complex models.
compareFn bool Function(T, T?)? Equality comparator for models.
popupItemBuilder Widget Function(...) Custom builder for popup list items.
dropdownBuilder Widget Function(...) Custom builder for single-selection input field.
dropdownBuilderMulti Widget Function(...) Custom builder for multi-selection input field.
popupItemDisabled bool Function(T)? Disable specific items from selection.
favoriteItems List<T> Function(List<T>)? Quick selection favorite chips displayed above list.
validator FormFieldValidator<T>? Form validation logic.

🀝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request or create an issue on GitHub.


πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.