SelectorListAppi
A flexible horizontal selector widget that displays items as chips or cards with optional icons, supporting single selection and customizable styling.
Features
- Horizontal Layout: Displays items in a scrollable horizontal list
- Single Selection: Select one item from the list
- Icon Support: Optional icons for each item
- Flexible Sizing: Customizable width, height, and spacing
- Scrollable: Automatically scrollable when content exceeds container width
- Custom Styling: Configurable text colors, alignment, and dimensions
- Form Integration: Works seamlessly with form validation
- Responsive Design: Adapts to different screen sizes and orientations
Usage
Basic Selector List
SelectorListAppi(
selected: _selectedOption,
dat: ['Option 1', 'Option 2', 'Option 3', 'Option 4'],
onTap: (selectedValue) {
setState(() => _selectedOption = selectedValue);
},
)
Selector List with Icons
SelectorListAppi(
selected: _selectedCategory,
dat: ['Home', 'Work', 'Personal', 'Travel'],
icons: [
Icons.home,
Icons.work,
Icons.person,
Icons.flight,
],
onTap: (selectedValue) {
setState(() => _selectedCategory = selectedValue);
},
)
Customized Selector List
SelectorListAppi(
selected: _selectedPriority,
dat: ['Low', 'Medium', 'High', 'Critical'],
heading: 'Priority Level',
mandatory: true,
minWidth: 80,
chipHeight: 45,
spacing: 12,
iconHeight: 20,
iconWidth: 20,
selectedTextColor: Colors.white,
unselectedTextColor: Colors.grey[600],
crossAlignment: CrossAxisAlignment.center,
onTap: (selectedValue) {
setState(() => _selectedPriority = selectedValue);
},
)
Parameters
| Name | Type | Description | Default |
|------|------|-------------|---------||
| selected
| String
| Required. Currently selected value | - |
| dat
| List<String>
| Required. List of options to display | - |
| onTap
| Function(String)
| Required. Callback when an item is tapped | - |
| icons
| List<IconData>?
| Optional list of icons for each item | null
|
| heading
| String?
| Optional heading text above the selector | null
|
| mandatory
| bool?
| Whether the field is required (shows asterisk) | false
|
| minWidth
| double?
| Minimum width for each chip | null
|
| chipHeight
| double?
| Height of each chip | null
|
| spacing
| double?
| Horizontal spacing between chips | 8.0
|
| iconPadding
| EdgeInsets?
| Padding around icons | null
|
| iconHeight
| double?
| Height of icons | null
|
| iconWidth
| double?
| Width of icons | null
|
| crossAlignment
| CrossAxisAlignment?
| Vertical alignment of items | CrossAxisAlignment.center
|
| scrollable
| bool?
| Whether the list should be scrollable | true
|
| selectedTextColor
| Color?
| Text color for selected item | null
|
| unselectedTextColor
| Color?
| Text color for unselected items | null
|
Behavior
Selection
- Only one item can be selected at a time
- Tapping an item selects it and deselects others
- Selected item is visually highlighted
- Callback is triggered on every selection change
Layout
- Items are arranged horizontally
- Automatically scrollable when content exceeds container width
- Spacing between items is customizable
- Icons (if provided) are displayed above text labels
Styling
- Selected and unselected items have different visual states
- Text colors can be customized for both states
- Icon and chip dimensions are configurable
- Supports custom alignment and spacing
Best Practices
- Item Count: Keep the number of items reasonable for horizontal scrolling
- Icon Consistency: If using icons, provide them for all items or none
- Text Length: Keep item labels short for better horizontal layout
- Spacing: Use appropriate spacing for touch targets (minimum 44px)
- Color Contrast: Ensure good contrast between selected/unselected states
- Accessibility: Provide meaningful labels and ensure proper touch targets
Examples
Category Selection
SelectorListAppi(
selected: _selectedCategory,
dat: ['All', 'Work', 'Personal', 'Shopping', 'Health'],
icons: [
Icons.apps,
Icons.work,
Icons.person,
Icons.shopping_cart,
Icons.health_and_safety,
],
heading: 'Category',
chipHeight: 50,
spacing: 10,
iconHeight: 24,
iconWidth: 24,
selectedTextColor: Colors.white,
unselectedTextColor: Colors.grey[700],
onTap: (category) {
setState(() => _selectedCategory = category);
_filterByCategory(category);
},
)
Priority Selector
SelectorListAppi(
selected: _selectedPriority,
dat: ['Low', 'Medium', 'High', 'Urgent'],
heading: 'Priority',
mandatory: true,
minWidth: 70,
chipHeight: 40,
spacing: 8,
selectedTextColor: Colors.white,
unselectedTextColor: Colors.black87,
onTap: (priority) {
setState(() => _selectedPriority = priority);
_updateTaskPriority(priority);
},
)
Status Filter
SelectorListAppi(
selected: _selectedStatus,
dat: ['Pending', 'In Progress', 'Completed', 'Cancelled'],
icons: [
Icons.schedule,
Icons.play_arrow,
Icons.check_circle,
Icons.cancel,
],
heading: 'Filter by Status',
chipHeight: 45,
spacing: 12,
iconHeight: 20,
iconWidth: 20,
crossAlignment: CrossAxisAlignment.center,
selectedTextColor: Colors.white,
unselectedTextColor: Colors.grey[600],
onTap: (status) {
setState(() => _selectedStatus = status);
_applyStatusFilter(status);
},
)
Time Period Selector
SelectorListAppi(
selected: _selectedPeriod,
dat: ['Today', 'This Week', 'This Month', 'This Year'],
heading: 'Time Period',
minWidth: 90,
chipHeight: 38,
spacing: 10,
selectedTextColor: Colors.blue[700],
unselectedTextColor: Colors.grey[500],
onTap: (period) {
setState(() => _selectedPeriod = period);
_loadDataForPeriod(period);
},
)
Form Integration
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SelectorListAppi(
selected: _selectedType,
dat: ['Income', 'Expense', 'Transfer'],
icons: [
Icons.arrow_downward,
Icons.arrow_upward,
Icons.swap_horiz,
],
heading: 'Transaction Type',
mandatory: true,
chipHeight: 50,
spacing: 15,
iconHeight: 24,
iconWidth: 24,
selectedTextColor: Colors.white,
unselectedTextColor: Colors.black87,
onTap: (type) {
setState(() => _selectedType = type);
_updateFormFields(type);
},
),
SizedBox(height: 20),
SelectorListAppi(
selected: _selectedFrequency,
dat: ['Once', 'Daily', 'Weekly', 'Monthly'],
heading: 'Frequency',
minWidth: 80,
chipHeight: 40,
spacing: 10,
selectedTextColor: Colors.green[700],
unselectedTextColor: Colors.grey[600],
onTap: (frequency) {
setState(() => _selectedFrequency = frequency);
},
),
],
)
Scrollable Long List
SelectorListAppi(
selected: _selectedCountry,
dat: [
'USA', 'Canada', 'UK', 'Germany', 'France',
'Italy', 'Spain', 'Australia', 'Japan', 'India'
],
heading: 'Select Country',
scrollable: true,
minWidth: 80,
chipHeight: 42,
spacing: 8,
selectedTextColor: Colors.white,
unselectedTextColor: Colors.black54,
onTap: (country) {
setState(() => _selectedCountry = country);
_loadCountryData(country);
},
)
Custom Styled Selector
SelectorListAppi(
selected: _selectedTheme,
dat: ['Light', 'Dark', 'Auto'],
icons: [
Icons.light_mode,
Icons.dark_mode,
Icons.auto_mode,
],
heading: 'Theme Preference',
chipHeight: 55,
spacing: 15,
iconHeight: 28,
iconWidth: 28,
iconPadding: EdgeInsets.only(bottom: 4),
crossAlignment: CrossAxisAlignment.center,
selectedTextColor: Colors.white,
unselectedTextColor: Colors.grey[700],
onTap: (theme) {
setState(() => _selectedTheme = theme);
_applyTheme(theme);
},
)
See Also
- SearchChipAppi - For searchable chip selection
- DropDownFieldAppi - For dropdown-style selection
- ButtonAppi - For button-style interactions