Easily convert your usual single/multiple select or dropdown into page, dialog, or bottom sheet with various choice input such as radio, checkbox, switch, chips, or custom widget.
Package selection guidance compiled from public package information, community data, and project usage.
flutter_awesome_select is a Flutter package that enhances standard dropdowns and selection widgets by enabling them to appear as pages, dialogs, or bottom sheets. It supports multiple choice types including radio buttons, checkboxes, switches, chips, and custom widgets, offering flexible and visually appealing input options. The package simplifies the creation of interactive selection interfaces with minimal code, improving user experience across different screen layouts. It’s ideal for forms, filters, and settings where users need to choose one or more options from a list.
May increase bundle size with extensive custom widgets
Not optimized for very large datasets
Depends on external dependencies for advanced features
Original README
Original README snapshot from the linked source repository. Visit the repository for the latest content.
About
SmartSelect allows you to easily convert your usual form select or dropdown into dynamic page, popup dialog, or sliding bottom sheet with various choices input such as radio, checkbox, switch, chips, or even custom input. Supports single and multiple choice. Inspired by Smart Select component from Framework7.
Features
Customizable every part on modal widget (header, footer, searchbar, confirm button, searchbar toggle) using style configuration or widget builder
Validate before confirm
Auto search on type
Accent marks handler on search
Highlight search result
Chips tile widget
Grid choice layout
Horizotal or vertical choice list scroll direction
Simplify class name and enum
Configurations supports copyWith and merge
Use StatefulWidget as state management
Easy shortcut to define configuration
Soft depends to other package
To Do
Right-To-Left parameter support, currently this can be achieved using widget builder
Internally handle async choice items loader
Custom search handler
Choice items pagination (pull to refresh and pull to load more)
Add more test
Migration from 4.0.0 to 4.2.0
modalValidation function nows should return String to indicates the changes value is not valid and null or empty String to indicates the changes value is valid
To display tile with chips use param S2Tile.body and S2TileChips, instead of S2ChipsTile
Migration from 3.0.x to 4.0.0
The parameter options is removed, instead use choiceItems
Simplify class name and enum
SmartSelectTile to S2Tile
SmartSelectOption to S2Choice
SmartSelectChoiceConfig to S2ChoiceConfig
SmartSelectChoiceStyle to S2ChoiceStyle
SmartSelectChoiceType to S2ChoiceType
SmartSelectModalConfig to S2ModalConfig
SmartSelectModalStyle to S2ModalStyle
SmartSelectModalHeaderStyle to S2ModalHeaderStyle
SmartSelectModalType to S2ModalType
The parameter builder now is a collection of builder (S2SingleBuilder or S2MultiBuilder), instead use tileBuilder to create trigger tile widget.
The parameters dense, enabled, isLoading, isTwoLine, leading, loadingText, padding, selected, trailing is removed from SmartSelect class, instead use builder.tile or tileBuilder and return S2Tile widget, it's has all these parameters.
The parameter onChange nows return S2SingleState state or S2MultiState state instead of T value or List<T> value
The parameter choiceConfig.useWrap is removed, instead use choiceConfig.layout = S2ChoiceLayout.wrap
The parameter choiceConfig.builder moved to builder.choice or choiceBuilder
The parameter choiceConfig.titleBuilder moved to builder.choiceTitle or choiceTitleBuilder
The parameter choiceConfig.subtitleBuilder moved to builder.choiceSubtitle or choiceSubtitleBuilder
The parameter choiceConfig.secondaryBuilder moved to builder.choiceSecondary or choiceSecondaryBuilder
The parameter choiceConfig.dividerBuilder moved to builder.choiceDivider or choiceDividerBuilder
The parameter choiceConfig.emptyBuilder moved to builder.choiceEmpty or choiceEmptybuilder
The parameter choiceConfig.glowingOverscrollIndicatorColor is removed, instead use choiceConfig.overscrollColor
The parameter choiceConfig.spacing and choiceConfig.runSpacing moved to choiceConfig.style.spacing and choiceConfig.style.runSpacing
The parameter choiceConfig.useCheckmark moved to choiceConfig.style.showCheckmark
The parameter choiceConfig.padding moved to choiceConfig.style.wrapperPadding
The default of grouped choice is not using sticky header now, instead use groupBuilder like this:
To read more about classes and other references used by smart_select, see the API Reference.
Single Choice
// available configuration for single choiceSmartSelect<T>.single({
// The primary content of the widget.// Used in trigger widget and header optionString title,
// The text displayed when the value is nullString placeholder = 'Select one',
// The current value of the single choice widget.required T value,
// Called when single choice value changedrequiredValueChanged<S2SingleState<T>> onChange,
// choice item listList<S2Choice<T>> choiceItems,
// other available configuration// explained below
...,
...,
})
// available configuration for multiple choiceSmartSelect<T>.multiple({
// The primary content of the widget.// Used in trigger widget and header optionString title,
// The text displayed when the value is nullString placeholder = 'Select one',
// The current value of the single choice widget.requiredList<T> value,
// Called when single choice value changedrequiredValueChanged<S2MultiState<T>> onChange,
// choice item listList<S2Choice<T>> choiceItems,
// other available configuration// explained below
...,
...,
})
More info about S2ModalConfig can be found on the API Reference
// available configurationSmartSelect<T>.[single|multiple]({
// other configuration
...,
...,
// Modal validation of single choice widgetValidationCallback<T> modalValidation,
// Modal configurationS2ModalConfig modalConfig,
// Configure modal style// shortcut to [modalConfig.style]S2ModalStyle modalStyle,
// Configure modal header style// shortcut to [modalConfig.headerStyle]S2ModalHeaderStyle modalHeaderStyle,
// Modal type to display choices// shortcut to [modalConfig.type]S2ModalType modalType,
// Use different title with the trigger widget title// shortcut to [modalConfig.title]String modalTitle,
// Whether the option list need to confirm// to return the changed value// shortcut to [modalConfig.useConfirm]bool modalConfirm,
// Whether the options list modal use header or not// shortcut to [modalConfig.useHeader]bool modalHeader,
// Whether the option list is filterable or not// shortcut to [modalConfig.useFilter]bool modalFilter,
// Whether the filter is autocomplete or need confirmation// shortcut to [modalConfig.filterAuto]bool modalFilterAuto,
// Custom searchbar hint// shortcut to [modalConfig.filterHint]String modalFilterHint,
// other configuration
...,
...,
});
Modal Type
By default SmartSelect will open choices modal in full page. You can change it by changing with this value:
// Available optionenumS2ModalType {
// open in full page
fullPage,
// open in popup dialog
popupDialog,
// open in sliding bottom sheet
bottomSheet,
}
Modal Style
// Available option to configure modal styleS2ModalStyle({
// Modal border shape// used in popup dialog and bottom sheetShapeBorder shape,
// Modal elevation// used in popup dialog and bottom sheetdouble elevation,
// Modal background colorColor backgroundColor,
// Modal clip behaviorClip clipBehavior,
})
Modal Header Style
// Available option to configure modal header styleS2ModalHeaderStyle({
// Header border shapeShapeBorder shape,
// Header elevationdouble elevation,
// Header background colorColor backgroundColor,
// Header brightnessBrightness brightness,
// Whether the header title is centeredbool centerTitle,
// Whether the header use automaticallyImplyLeading or notbool useLeading,
// Header text style// used by title and search fieldTextStyle textStyle,
// Header icon themeIconThemeData iconTheme,
// Header actions icon themeIconThemeData actionsIconTheme,
})
Choices Configuration
More info about S2ChoiceConfig can be found on the API Reference
// Available option to configure choicesSmartSelect<T>.[single|multiple]({
// other configuration
...,
...,
// choice configurationS2ChoiceConfig choiceConfig,
// configure choice style// shortcut to [choiceConfig.style]S2ChoiceStyle choiceStyle,
// configure choices group header style// shortcut to [choiceConfig.headerStyle]S2ChoiceHeaderStyle choiceHeaderStyle,
// choice widget type// shortcut to [choiceConfig.type]S2ChoiceType choiceType,
// choice layout to display items// shortcut to [choiceConfig.layout]S2ChoiceLayout choiceLayout,
// choice list scroll direction// currently only support when// [layout] is [S2ChoiceLayout.wrap]// shortcut to [choiceConfig.direction]Axis choiceDirection,
// Whether the choices list is grouped// shortcut to [choiceConfig.isGrouped]bool choiceGrouped,
// Whether the choices item use divider or not// shortcut to [choiceConfig.useDivider]bool choiceDivider,
// For grid choice layout// shortcut to [choiceConfig.gridDelegate]SliverGridDelegate choiceGrid,
// other configuration
...,
...,
});
Choice Type
By default SmartSelect will use radios for single choice and checkboxes for multiple choice, but it can change by changing with this value:
// Type of choice inputenumS2ChoiceType {
// use radio widget// for single choice
radios,
// use checkbox widget// for multiple choice
checkboxes,
// use switch widget// for multiple choice
switches,
// use chip widget// for single and multiple choice
chips,
}
Choice Layout
By default SmartSelect will use list, but it can change by changing with this value:
// Layout of choice itemenumS2ChoiceLayout {
// use list view widget
list,
// use wrap view widget
wrap,
// use grid view widget
grid,
}
Choice Styles
// Available option to configure choice styleS2ChoiceStyle({
// How much space to place between children in a run in the main axis.// When use [SmartSelectChoiceType.chips] or [useWrap] is [true]double spacing,
// How much space to place between the runs themselves in the cross axis.// When use [SmartSelectChoiceType.chips] or [useWrap] is [true]double runSpacing,
// choices wrapper paddingEdgeInsetsGeometry wrapperPadding,
// Choices item paddingEdgeInsetsGeometry padding,
// choices item title styleTextStyle titleStyle,
// choices item subtitle styleTextStyle subtitleStyle,
// whether the chips use checkmark or notbool showCheckmark,
// Where to place the control in widgets that use// [ListTile] to position a control next to a label.S2ChoiceControl control,
// Highlight colorColor highlightColor,
// Primary color of selected choice itemColor activeColor,
// Primary color of unselected choice itemColor color,
// Secondary color of selected choice itemColor activeAccentColor,
// Secondary color of unselected choice itemColor accentColor,
// Brightness for selected ChipBrightness activeBrightness,
// Brightness for unselected ChipBrightness brightness,
// Opacity for selected Chip border, only effect when// [activeBrightness] is [Brightness.light]double activeBorderOpacity,
// Opacity for unselected chip border, only effect when// [brightness] is [Brightness.light]double borderOpacity,
// Shape clip behaviorClip clipBehavior,
})
Choice Header Style
// Available option to configure choices group header widget styleS2ChoiceHeaderStyle({
// Group header background colorColor backgroundColor,
// Highlight colorColor highlightColor,
// Group header text styleTextStyle textStyle,
// Group header paddingEdgeInsetsGeometry padding,
// Group header heightdouble height,
})
Builder Widget
Builder for Single Choice
// available builder configuration// for single choiceSmartSelect<T>.single({
// other configuration
...,
...,
// Builder collection of single choice widgetS2SingleBuilder<T> builder,
// Builder for custom tile widget// shortcut to [builder.tile]S2WidgetBuilder<S2SingleState<T>> tileBuilder,
// Builder for custom modal widget// shortcut to [builder.modal]S2WidgetBuilder<S2SingleState<T>> modalBuilder,
// Builder for custom modal header widget// shortcut to [builder.modalHeader]S2WidgetBuilder<S2SingleState<T>> modalHeaderBuilder,
// Builder for custom modal actions widget// shortcut to [builder.modalActions]S2ListWidgetBuilder<S2SingleState<T>> modalActionsBuilder,
// Builder for custom modal confirm action widget// shortcut to [builder.modalConfirm]S2WidgetBuilder<S2SingleState<T>> modalConfirmBuilder,
// Builder for divider widget between header, body, and footer modal// shortcut to [builder.modalDivider]S2WidgetBuilder<S2SingleState<T>> modalDividerBuilder,
// Builder for custom footer widget// shortcut to [builder.modalFooter]S2WidgetBuilder<S2SingleState<T>> modalFooterBuilder,
// other configuration
...,
...,
});
Builder for Multiple Choice
// available builder configuration// for multiple choiceSmartSelect<T>.multiple({
// other configuration
...,
...,
// Builder collection of single choice widgetS2MultiBuilder<T> builder,
// Builder for custom tile widget// shortcut to [builder.tile]S2WidgetBuilder<S2MultiState<T>> tileBuilder,
// Builder for custom modal widget// shortcut to [builder.modal]S2WidgetBuilder<S2MultiState<T>> modalBuilder,
// Builder for custom modal header widget// shortcut to [builder.modalHeader]S2WidgetBuilder<S2MultiState<T>> modalHeaderBuilder,
// Builder for custom modal actions widget// shortcut to [builder.modalActions]S2ListWidgetBuilder<S2MultiState<T>> modalActionsBuilder,
// Builder for custom modal confirm action widget// shortcut to [builder.modalConfirm]S2WidgetBuilder<S2MultiState<T>> modalConfirmBuilder,
// Builder for divider widget between header, body, and footer modal// shortcut to [builder.modalDivider]S2WidgetBuilder<S2MultiState<T>> modalDividerBuilder,
// Builder for custom footer widget// shortcut to [builder.modalFooter]S2WidgetBuilder<S2MultiState<T>> modalFooterBuilder,
// other configuration
...,
...,
});
Other Builder
// another builder configurationSmartSelect<T>.[single|multiple]({
// other configuration
...,
...,
// Builder for modal filter widget// shortcut to [builder.modalFilter]S2WidgetBuilder<S2Filter> modalFilterBuilder,
// Builder for modal filter toggle widget// shortcut to [builder.modalFilterToggle]S2WidgetBuilder<S2Filter> modalFilterToggleBuilder,
// Builder for each custom choices item widget// shortcut to [builder.choice]S2ChoiceBuilder<T> choiceBuilder,
// Builder for each custom choices item title widget// shortcut to [builder.choiceTitle]S2ChoiceBuilder<T> choiceTitleBuilder,
// Builder for each custom choices item subtitle widget// shortcut to [builder.choiceSubtitle]S2ChoiceBuilder<T> choiceSubtitleBuilder,
// Builder for each custom choices item secondary widget// shortcut to [builder.choiceSecondary]S2ChoiceBuilder<T> choiceSecondaryBuilder,
/// Builder for custom divider widget between choices item// shortcut to [builder.choiceDivider]IndexedWidgetBuilder choiceDividerBuilder,
// Builder for custom empty display// shortcut to [builder.choiceEmpty]S2WidgetBuilder<String> choiceEmptyBuilder,
// A widget builder for custom choices group// shortcut to [builder.choiceGroup]S2ChoiceGroupBuilder choiceGroupBuilder,
// A widget builder for custom header choices group// shortcut to [builder.choiceHeader]S2ChoiceHeaderBuilder choiceHeaderBuilder,
// other configuration
...,
...,
});
Tile Widget
Default Tile
// Default tile/trigger widgetS2Tile<T>({
// The value of the selected option.String value,
// The primary content of the list tile.Widget title,
// A widget to display before the title.// Typically an [Icon] or a [CircleAvatar] widget.Widget leading,
// A widget to display after the title.// Typically an [Icon] widget.Widget trailing,
// Whether this list tile is intended to display loading stats.bool isLoading,
// String text used as loading textString loadingText,
// Whether this list tile is intended to display two lines of text.bool isTwoLine,
// Whether this list tile is interactive.bool enabled,
// If this tile is also [enabled] then icons and text are rendered with the same color.bool selected,
// Whether this list tile is part of a vertically dense list.bool dense,
// Whether the [value] is displayed or notbool hideValue,
// The tile's internal padding.EdgeInsetsGeometry padding,
// Called when the user taps this list tile.GestureTapCallback onTap,
// widget to display below the tile// usually used to display chips with S2TileChipsWidget body,
})
// Chips tile/trigger widgetS2TileChips({
// List of value of the selected choices.int chipLength,
// Widget builder for chip label itemIndexedWidgetBuilder chipLabelBuilder,
// Widget builder for chip avatar itemIndexedWidgetBuilder chipAvatarBuilder,
// Widget builder for chip itemIndexedWidgetBuilder chipBuilder,
// Called when the user delete the chip item.ValueChanged<int> chipOnDelete,
// Chip colorColor chipColor,
// Chip border opacitydouble chipBorderOpacity,
// Chip brightnessBrightness chipBrightness,
// Chip delete button colorColor chipDeleteColor,
// Chip delete button iconIcon chipDeleteIcon,
// Chip spacingdouble chipSpacing,
// Chip run spacingdouble chipRunSpacing,
// Chip shape borderShapeBorder chipShape,
// The [Widget] displayed when the [values] is nullWidget placeholder,
// Whether the chip list is scrollable or notbool scrollable,
// Chip list paddingEdgeInsetsGeometry padding,
})
Copyright (c) 2021AkbarPulatovPermissionis hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Softwareis
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.