Dropdown menus are a common UI component in Flutter, but sometimes you need something more personalized to fit your app’s design. This tutorial walks you through creating a custom dropdown color menu in Flutter. You’ll learn how to display color options in a dropdown and allow users to select one, with the selected color updating the UI dynamically.
Step 1: Setting Up the Flutter Project
1. Create a new Flutter project or open an existing one:flutter create custom_dropdown_menu cd custom_dropdown_menu
Step 2: Building the Color Dropdown Menu
To create a dropdown menu that displays color options, we’ll use Flutter’s DropdownButton
widget. However, we’ll customize it to show color swatches instead of regular text.
Code: Custom Dropdown Color Menu
Below is the full implementation:
import 'package:flutter/material.dart'; void main() { runApp(ColorDropdownApp()); } class ColorDropdownApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, home: ColorDropdownScreen(), ); } } class ColorDropdownScreen extends StatefulWidget { @override _ColorDropdownScreenState createState() => _ColorDropdownScreenState(); } class _ColorDropdownScreenState extends State<ColorDropdownScreen> { // List of colors for the dropdown final List<Color> colors = [ Colors.red, Colors.green, Colors.blue, Colors.yellow, Colors.purple, Colors.orange, ]; // Currently selected color Color selectedColor = Colors.red; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Custom Dropdown Color Menu'), backgroundColor: selectedColor, ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( 'Select a Color:', style: TextStyle(fontSize: 20), ), SizedBox(height: 20), // Dropdown Button DropdownButton<Color>( value: selectedColor, icon: Icon(Icons.arrow_drop_down), iconSize: 24, elevation: 16, dropdownColor: Colors.white, style: TextStyle(color: Colors.black), onChanged: (Color? newColor) { setState(() { selectedColor = newColor!; }); }, items: colors.map<DropdownMenuItem<Color>>((Color color) { return DropdownMenuItem<Color>( value: color, child: Container( width: 100, height: 20, color: color, ), ); }).toList(), ), SizedBox(height: 40), // Display selected color Text( 'You selected:', style: TextStyle(fontSize: 18), ), Container( width: 100, height: 100, color: selectedColor, ), ], ), ), ); } }
Step 3: Running the Application
1. Save the code tomain.dart
.2. Run the application
flutter run
Output
How It Works
1. DropdownButton Widget:
- Displays a list of color options in a dropdown menu.
- The
DropdownButton
widget hasitems
, which is a list ofDropdownMenuItem
widgets. Each menu item contains aContainer
filled with a color swatch.
2. Dynamic State Update:
- The
onChanged
callback updates theselectedColor
variable whenever a new color is chosen, triggering a rebuild of the widget tree to reflect the updated color.
- The selected color is displayed in a square box below the dropdown.
Code Enhancement
Let's enhance the custom dropdown menu to use a List<Map<String, dynamic>>
instead of List<Color>
. This allows us to associate a name with each color, making the menu more informative and flexible.
Updated Code: Custom Dropdown with Color Names
Here’s the enhanced version of the code:
import 'package:flutter/material.dart'; void main() { runApp(ColorDropdownApp()); } class ColorDropdownApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, home: ColorDropdownScreen(), ); } } class ColorDropdownScreen extends StatefulWidget { @override _ColorDropdownScreenState createState() => _ColorDropdownScreenState(); } class _ColorDropdownScreenState extends State<ColorDropdownScreen> { // List of colors with names final List<Map<String, dynamic>> _colors = [ {'name': 'Red', 'color': Colors.red}, {'name': 'Green', 'color': Colors.green}, {'name': 'Blue', 'color': Colors.blue}, {'name': 'Yellow', 'color': Colors.yellow}, {'name': 'Purple', 'color': Colors.purple}, {'name': 'Orange', 'color': Colors.orange}, ]; // Currently selected color Map<String, dynamic> _selectedColor = {'name': 'Red', 'color': Colors.red}; String _selectedColorName = 'Red'; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Enhanced Dropdown Color Menu'), backgroundColor: _selectedColor['color'], ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( 'Select a Color:', style: TextStyle(fontSize: 20), ), SizedBox(height: 20), // Dropdown Button Container( // Set the background color of the container dynamically decoration: BoxDecoration( color: _selectedColor['color'], borderRadius: BorderRadius.circular(8.0), ), padding: EdgeInsets.symmetric(horizontal: 8.0), child: DropdownButtonHideUnderline( child: DropdownButton<String>( // Define the dropdown items items: _colors.map((colorMap) { return DropdownMenuItem<String>( value: colorMap['name'], child: Row( children: [ Container( width: 20, height: 20, color: colorMap['color'], // Display color preview margin: const EdgeInsets.only(right: 8), ), Text(colorMap['name']), ], ), ); }).toList(), // Hint text hint: Text( _selectedColorName, style: TextStyle(color: Colors.white), ), onChanged: (String? selectedName) { setState(() { _selectedColorName = selectedName!; // Update background color based on the selected color _selectedColor = _colors.firstWhere((element) => element['name'] == selectedName); }); }, ), ), ), ], ), ), ); } }
Output of the enhanced code
Explanation of Enhancements
1. Using List<Map<String, dynamic>>
:
- Each color is represented as a map with
name
andcolor
keys:
{'name': 'Red', 'color': Colors.red}
2. Updated _selectedColor
State:
- The dropdown now holds a map for the selected color:
Map<String, dynamic> _selectedColor = {'name': 'Red', 'color': Colors.red};
3. Wrapped DropdownButton
with the container and removed the underline.
- Once the selected color menu is changed then the container background will be updated.
Container( // Set the background color of the container dynamically decoration: BoxDecoration( color: _selectedColor['color'], borderRadius: BorderRadius.circular(8.0), ), padding: EdgeInsets.symmetric(horizontal: 8.0), child: DropdownButtonHideUnderline( child: ...), ),
DropdownMenuItem
:- Each menu item displays a small color swatch alongside the color name using a
Row
widget:
return DropdownMenuItem<String>( value: colorMap['name'], child: Row( children: [ Container( width: 20, height: 20, color: colorMap['color'], // Display color preview margin: const EdgeInsets.only(right: 8), ), Text(colorMap['name']), ], ), );
5. Dynamic Updates:
- When a new color is selected, the
onChanged
callback updates_selectedColor
, triggering a UI refresh to reflect the selected color and its name.
How It Works
- The dropdown uses the
_colors
list to generate menu items. - Each menu item is a combination of a color swatch and the color name.
- When the user selects a color, the
onChanged
callback updates_selectedColor
. - The app bar and the color preview box update dynamically based on the selected color.
List<Map>
makes the implementation more flexible and extendable. You can now easily add more properties (e.g., hex codes, descriptions) to the colors if needed.