group_dropdown_button 1.0.3
group_dropdown_button: ^1.0.3 copied to clipboard
GroupDropdownButton - A versatile Flutter widget for grouped, searchable, and recursive dropdowns. Perfect for hierarchical selections with a Material Design look.
π§© GroupDropdownButton #
A powerful, customizable Flutter widget for rendering grouped, searchable, recursive dropdowns with support for radio buttons, check indicators, and dynamic overlays.
Ideal for apps that require deeply nested, categorized selections with a sleek Material look.
π Table of Contents #
- π Features
- πΈ Screenshots
- π οΈ Installation
- π Usage
- π¨ Customization Options
- π§± GroupedDropdownOption Data Structure
- π Package Folder Structure (for reference)
- π€ Contributing
- π License
π Features #
- β Grouped dropdown items with support for recursive nesting
- π Live search & filtering
- π§© Custom prefix/suffix widgets
- π― Radio button or check icon for selected item
- π Fully customizable styling and borders
- π Overlay-based dropdown with smart positioning
- π ExpansionTile-based group rendering
- β οΈ Inline error display and required field validation
πΈ Screenshots #
GroupDropdownButton
#

Selected item response from onSelect

showCheckForSelected
- takes boolean value and displays check icon on selected item, true to enable & false to disable, default false
Check Icon enabled | Check Icon disabled |
---|---|
![]() |
![]() |
checkWidgetForSelectedItem
- takes Widget can replace check icon widget with custom widget, checkWidgetForSelectedItem: Icon(Icons.abc)
, deafult null

itemPrefix
- takes Widget, adds widget as prefix to every item not for group title, default null
itemPrefix: Icon(Icons.arrow_forward) |
itemPrefix: Icon(Icons.adb_sharp) |
---|---|
![]() |
![]() |
showDividerBtwGroups
- takes boolean value and displays divider between groups, true to show & false to hide, default false

If any options have not items to select that is considered as item not as group

enabledRadioForItems
- takes boolean value and displays radio button as prefix to every item not for group title, true to show & false to hide, default false

eachGroupIsExpansion
- takes boolean value and renders nested groups with ExpansionTile
, true to enable & false to disable, default false

borderType
- takes enum TextFieldInputBorder
, to show outline border or underline border to the textfield, default TextFieldInputBorder.outLine
borderType: TextFieldInputBorder.outLine |
borderType: TextFieldInputBorder.underLine |
---|---|
![]() |
![]() |
isRequired
- takes boolean value and manages to enable or disable validator to the textfield, default false
errorText
- tabkes string value and overides the default error message to custom error message, default This field is required
, works only if isRequired
is true
isRequired: true |
isRequired: true, errorText: "Oops! Please pick an item." |
---|---|
![]() |
![]() |
π οΈ Installation #
-
Add this gem to your package's
pubspec.yaml
file:dependencies: group_dropdown_button: ^latest_version # π Replace with the actual version from pub.dev
-
Install it by running:
flutter pub get
π Usage #
1. Import the Package #
import 'package:group_dropdown_button/group_dropdown_button.dart';
2. Define Your Data #
Structure your items using the GroupedDropdownOption
class. Each group can contain subItems
.
final List<GroupedDropdownOption> myCategorizedItems = [
GroupedDropdownOption(
key: "fruits",
title: "π Fruits", // Emojis in titles can be fun!
subItems: [
GroupedDropdownOption(key: "apple", title: "Apple"),
GroupedDropdownOption(key: "banana", title: "Banana"),
GroupedDropdownOption(key: "orange", title: "Orange"),
],
),
GroupedDropdownOption(
key: "vegetables",
title: "π₯¦ Vegetables",
subItems: [
GroupedDropdownOption(key: "carrot", title: "Carrot"),
GroupedDropdownOption(key: "broccoli", title: "Broccoli"),
GroupedDropdownOption(key: "spinach", title: "Spinach"),
],
),
// Add more groups as needed.
// Remember: You need at least two top-level GroupedDropdownOption items.
];
3. Use the GroupDropdownButton
Widget #
Here's a practical example:
GroupDropdownButton(
items: myCategorizedItems,
onSelect: (GroupedDropdownOption? selectedOption) {
setState(() {
_selectedItem = selectedOption;
});
if (selectedOption != null) {
print('Selected: ${selectedOption.title} (Key: ${selectedOption.key})');
print('Parent: ${selectedOption.parentTitle} (Key: ${selectedOption.parentKey})');
if (selectedOption.extraInfo != null) {
print('Extra Info: ${selectedOption.extraInfo}');
}
}
},
// initialValue: myCategorizedItems.first.subItems?.first, // Example initial value
hintText: "Select an item...",
labelText: "Choose a Category",
buttonWidth: double.infinity,
isRequired: true,
errorText: "Oops! Please pick an item.",
// --- π¨ Explore further customization! ---
// itemPrefix: Icon(Icons.arrow_forward_ios, size: 14, color: Colors.blueGrey),
// eachGroupIsExpansion: true,
// showDividerBtwGroups: true,
// enabledRadioForItems: false, // Cannot be true if showCheckForSelected is true
// showCheckForSelected: true,
// checkWidgetForSelectedItem: Icon(Icons.task_alt_rounded, color: Colors.green, size: 20),
// borderRadius: 12.0,
// borderType: TextFieldInputBorder.outLine,
// focusedBorderColor: Colors.deepPurpleAccent,
)
π¨ Customization Options #
The GroupDropdownButton
is packed with properties to tailor its look and feel.
Quick Customization Overview #
Property | Description |
---|---|
buttonWidth |
Width of the dropdown trigger button |
isRequired |
Enables validation if true |
hintText , labelText |
Hint/Label display inside the text field |
hintStyle , labelStyle , textStyle |
Hint/Label/Textfield textstyle can be adjusted |
itemPrefix |
Adds a widget before every dropdown item |
showCheckForSelected |
Displays check icon on selected item |
enabledRadioForItems |
Displays radio button instead of check icon |
eachGroupIsExpansion |
Renders nested groups with ExpansionTile |
borderType |
Customizable input border type (outline, underline, etc) |
borderColor , focusedBorderColor , errorBorderColor |
Fine-tune border states |
Detailed Properties #
Core Properties
items
: (Required)List<GroupedDropdownOption>
- Your categorized data. Must not be empty and needs at least two top-level groups.onSelect
: (Required)ValueChanged<GroupedDropdownOption?>
- The heart of the selection! Callback when an item is chosen.initialValue
:GroupedDropdownOption?
- Pre-select an item to start.buttonWidth
:double
- Set the dropdown button's width (defaults to300.0
).
Item & Group Display
itemPrefix
:Widget?
- A leading widget for each selectable item in the list.enabledRadioForItems
:bool
- Show radio buttons for selection (defaults tofalse
). Note: Cannot betrue
ifshowCheckForSelected
istrue
.showCheckForSelected
:bool
- Display a check mark (or custom widget) next to the selected item (defaults tofalse
). Note: Cannot betrue
ifenabledRadioForItems
istrue
.checkWidgetForSelectedItem
:Widget?
- Your custom check mark widget ifshowCheckForSelected
istrue
.showDividerBtwGroups
:bool
- Add a visual separator line between groups (defaults tofalse
).eachGroupIsExpansion
:bool
- Make group titles act likeExpansionTile
headers (collapsible, defaults tofalse
).
Validation
isRequired
:bool
- Iftrue
, selection is mandatory for form validation (defaults tofalse
).errorText
:String?
- Custom error message for validation failures (defaults to "This field is required").
Theming π
The widget smartly adapts to your app's ThemeData
(text styles, primary color, error color, icon colors via AppContext
extension). You can always override these by providing specific color properties directly from your theme.
π§± GroupedDropdownOption
Data Structure #
This class is the blueprint for your dropdown items (both groups and their sub-items).
class GroupedDropdownOption {
final dynamic key; // Unique identifier (String, int, etc.)
final String title; // Display text for the option
final Map<String, dynamic>? extraInfo; // Optional bag for extra data
final List<GroupedDropdownOption>? subItems; // Child items for group options
final dynamic parentKey; // Auto-populated: Key of the parent group
final String? parentTitle; // Auto-populated: Title of the parent group
GroupedDropdownOption({
required this.key,
required this.title,
this.extraInfo,
this.subItems,
// parentKey and parentTitle are typically derived, not manually set for subItems.
});
}
π Package Folder Structure (for reference) #
lib
βββ group_dropdown_button.dart
βββ src
β βββ entity
β βββ dropdown_option_entity.dart
β βββ dropdown_return_item.dart
β βββ utils
β βββ enums.dart
β βββ extensions.dart
β βββ validations.dart
β βββ widgets
β βββ dropdown_button.dart
β βββ no_options.dart
β βββ text_field.dart
π€ Contributing #
Contributions make the open-source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated!
- Fork the Project
- Create your Feature Branch (
git checkout -b feature/AmazingFeature
) - Commit your Changes (
git commit -m 'Add some AmazingFeature'
) - Push to the Branch (
git push origin feature/AmazingFeature
) - Open a Pull Request
π License #
Distributed under the MIT License. See LICENSE
file for more information.