Skip to content

kihyun1998/flutter_dropdown_button

Repository files navigation

Flutter Dropdown Button

A highly customizable dropdown package for Flutter with overlay-based rendering, smooth animations, and full control over appearance and behavior — all in a single widget.

pub package License: MIT

Features

  • Single Unified Widget: One FlutterDropdownButton<T> for all use cases
  • Two Modes: Custom widget rendering (default) or text-only (.text())
  • Overlay-based Rendering: Better positioning and visual effects than Flutter's built-in DropdownButton
  • Smart Positioning: Automatically opens up/down based on available space
  • Smooth Animations: Scale and fade effects with configurable timing
  • Outside-tap Dismissal: Automatic closure when tapping outside
  • Flexible Width: Fixed, min/max constraints, content-based, or flex expansion
  • Independent Menu Width: Set menu width separately from button with alignment control
  • Text Overflow Control: Ellipsis, fade, clip, or visible overflow options
  • Smart Tooltip: Automatic tooltip on overflow with full customization
  • Custom Scrollbar: Scrollbar theming with colors, thickness, and visibility
  • Single-Item Mode: Auto-disable when only one option exists
  • Leading Widgets: Optional icons/widgets before text content

Screenshots

Basic Text Dropdown Icon + Text Dropdown with Hover
Basic Text Dropdown
Simple text options with customizable styles
Icon + Text Dropdown
Rich content with icons and hover effects

Quick Start

Add to your pubspec.yaml:

dependencies:
  flutter_dropdown_button: ^2.0.0

Import the package:

import 'package:flutter_dropdown_button/flutter_dropdown_button.dart';

Basic Usage

Text Dropdown (Fixed Width)

FlutterDropdownButton<String>.text(
  items: ['Apple', 'Banana', 'Cherry'],
  value: selectedValue,
  hint: 'Select a fruit',
  width: 200,
  onChanged: (value) {
    setState(() => selectedValue = value);
  },
)

Text Dropdown (Dynamic Width)

FlutterDropdownButton<String>.text(
  items: ['Apple', 'Banana', 'Cherry'],
  value: selectedValue,
  hint: 'Select a fruit',
  minWidth: 120,
  maxWidth: 300,
  onChanged: (value) {
    setState(() => selectedValue = value);
  },
)

Custom Widget Dropdown

FlutterDropdownButton<String>(
  items: ['home', 'settings', 'profile'],
  value: selectedValue,
  hintWidget: Text('Choose option'),
  itemBuilder: (item, isSelected) => Row(
    children: [
      Icon(_getIcon(item), size: 20),
      SizedBox(width: 8),
      Text(item),
    ],
  ),
  onChanged: (value) {
    setState(() => selectedValue = value);
  },
)

Custom Selected Display

FlutterDropdownButton<String>(
  items: ['apple', 'banana'],
  value: selectedValue,
  itemBuilder: (item, isSelected) => Text(item),
  selectedBuilder: (item) => Text(item.toUpperCase(),
    style: TextStyle(fontWeight: FontWeight.bold),
  ),
  onChanged: (value) {
    setState(() => selectedValue = value);
  },
)

API Reference

FlutterDropdownButton<T>

The unified dropdown widget. Use the default constructor for custom widget rendering, or .text() for text-only content.

Custom Mode (Default Constructor)

Parameter Type Default Description
items List<T> required List of item values
onChanged ValueChanged<T?> required Called when an item is selected
itemBuilder Widget Function(T, bool) required Builds widget for each item (item, isSelected)
selectedBuilder Widget Function(T)? null Builds widget for selected item on button face (falls back to itemBuilder)
hintWidget Widget? null Widget shown when no item is selected

Text Mode (.text Constructor)

Parameter Type Default Description
items List<T> required List of string items
onChanged ValueChanged<T?> required Called when an item is selected
hint String? null Text shown when no item is selected
config TextDropdownConfig? null Text rendering configuration
leading Widget? null Widget before text in all items
selectedLeading Widget? null Widget before text in selected item (falls back to leading)
leadingPadding EdgeInsets? right: 8.0 Padding around the leading widget

Common Parameters (Both Modes)

Parameter Type Default Description
value T? null Currently selected value
width double? null Fixed width (null = content-based)
minWidth double? null Minimum width constraint
maxWidth double? null Maximum width constraint
height double 200.0 Maximum height of dropdown overlay
itemHeight double 48.0 Height of each dropdown item
animationDuration Duration 200ms Duration of show/hide animation
enabled bool true Whether the dropdown is interactive
expand bool false Expand to fill available space in flex container
trailing Widget? null Custom widget replacing default arrow icon
scrollToSelectedItem bool true Auto-scroll to selected item on open
scrollToSelectedDuration Duration? null Scroll animation duration (null = instant jump)
disableWhenSingleItem bool false Disable dropdown when only one item exists
hideIconWhenSingleItem bool true Hide arrow icon in single-item mode
minMenuWidth double? null Minimum width of dropdown menu
maxMenuWidth double? null Maximum width of dropdown menu
menuAlignment MenuAlignment .left Menu alignment when wider than button
theme DropdownStyleTheme? null Theme configuration

MenuAlignment

Alignment of the dropdown menu relative to the button when the menu is wider.

Value Description
MenuAlignment.left Left edges align, menu extends right (default)
MenuAlignment.center Menu centered over button
MenuAlignment.right Right edges align, menu extends left

Theme System

Theme is applied via the theme parameter using DropdownStyleTheme, which groups three theme objects:

DropdownStyleTheme(
  dropdown: DropdownTheme(...),   // General dropdown styling
  scroll: DropdownScrollTheme(...), // Scrollbar styling
  tooltip: DropdownTooltipTheme(...), // Tooltip styling
)

DropdownTheme

Controls general styling for button, overlay, and items.

Button Styling

Parameter Type Default Description
buttonDecoration BoxDecoration? null Custom button decoration (overrides all below)
buttonPadding EdgeInsets horizontal: 16, vertical: 12 Internal padding of button
buttonHeight double? null Height of button content area (falls back to iconSize or 24.0)
buttonHoverColor Color? null Button hover background color
buttonSplashColor Color? null Button tap ripple color
buttonHighlightColor Color? null Button focus highlight color

Overlay Styling

Parameter Type Default Description
overlayDecoration BoxDecoration? null Custom overlay decoration (overrides backgroundColor, border, borderRadius)
overlayPadding EdgeInsets? null Padding inside the overlay container
borderRadius double 8.0 Border radius for button and overlay
elevation double 8.0 Shadow depth of overlay
backgroundColor Color? null Overlay background color (falls back to Theme.cardColor)
border Border? null Border for button and overlay (falls back to Theme.dividerColor)
shadowColor Color? null Overlay shadow color

Item Styling

Parameter Type Default Description
itemPadding EdgeInsets horizontal: 16, vertical: 12 Internal padding of each item
itemMargin EdgeInsets? null External margin around each item
itemBorderRadius double? null Border radius for individual items
itemBorder Border? null Border for each item (e.g., bottom divider)
excludeLastItemBorder bool true Skip itemBorder on the last item
selectedItemColor Color? null Background color for selected item (falls back to primaryColor 10%)
itemHoverColor Color? null Item hover background color
itemSplashColor Color? null Item tap ripple color
itemHighlightColor Color? null Item focus highlight color

Icon Styling

Parameter Type Default Description
icon IconData? Icons.keyboard_arrow_down Dropdown arrow icon
iconSize double? 24.0 Size of the dropdown icon
iconColor Color? null Icon color when enabled
iconDisabledColor Color? null Icon color when disabled
iconPadding EdgeInsets? EdgeInsets.only(left: 8.0) Padding around the icon

DropdownScrollTheme

Controls scrollbar appearance inside the dropdown overlay.

Parameter Type Default Description
thumbWidth double? null Width of the scrollbar thumb
trackWidth double? null Width of the scrollbar track
radius Radius? null Corner radius of scrollbar thumb
thumbColor Color? null Color of the scrollbar thumb
trackColor Color? null Color of the scrollbar track
trackBorderColor Color? null Border color of the scrollbar track
thumbVisibility bool? null Show/hide scrollbar thumb
trackVisibility bool? null Show/hide scrollbar track
interactive bool? null Allow dragging the scrollbar thumb
crossAxisMargin double? null Margin from edge of scroll view
mainAxisMargin double? null Margin at top/bottom of scrollbar
minThumbLength double? null Minimum length of scrollbar thumb
showScrollGradient bool? false Show fade gradient when scrollable
gradientHeight double? 24.0 Height of gradient effect
gradientColors List<Color>? null Custom gradient colors (auto-detects from background if null)

DropdownTooltipTheme

Controls tooltip styling and behavior for text-based dropdowns.

Visual Styling

Parameter Type Default Description
decoration Decoration? null Custom tooltip decoration
backgroundColor Color? null Tooltip background color
textColor Color? null Tooltip text color
textStyle TextStyle? null Tooltip text style (overrides textColor)
borderRadius BorderRadius? null Tooltip corner radius
borderColor Color? null Tooltip border color
borderWidth double? 1.0 Tooltip border width
shadow List<BoxShadow>? null Tooltip shadow
padding EdgeInsetsGeometry? null Padding inside tooltip
margin EdgeInsetsGeometry? null Margin around tooltip

Behavior

Parameter Type Default Description
enabled bool true Enable/disable tooltip
mode TooltipMode .onlyWhenOverflow When to show tooltip
waitDuration Duration 500ms Delay before showing on hover
showDuration Duration 3s How long tooltip stays visible
verticalOffset double? null Gap between widget and tooltip
triggerMode TooltipTriggerMode? null How tooltip is triggered

TextDropdownConfig

Configuration for text rendering in .text() mode.

Parameter Type Default Description
overflow TextOverflow .ellipsis How to handle text overflow
maxLines int? 1 Maximum number of lines
textStyle TextStyle? null Style for item text
hintStyle TextStyle? null Style for hint text
selectedTextStyle TextStyle? null Style for selected item text
textAlign TextAlign .start Horizontal text alignment
softWrap bool true Allow line breaks at word boundaries

Advanced Features

Custom Theme

FlutterDropdownButton<String>.text(
  items: items,
  value: selected,
  width: 200,
  theme: DropdownStyleTheme(
    dropdown: DropdownTheme(
      borderRadius: 12.0,
      elevation: 4.0,
      backgroundColor: Colors.white,
      selectedItemColor: Colors.blue.withOpacity(0.1),
      itemHoverColor: Colors.grey.withOpacity(0.1),
      itemBorder: Border(bottom: BorderSide(color: Colors.grey.shade300)),
      excludeLastItemBorder: true,
    ),
    scroll: DropdownScrollTheme(
      thumbWidth: 6.0,
      thumbColor: Colors.blue,
      showScrollGradient: true,
    ),
    tooltip: DropdownTooltipTheme(
      backgroundColor: Colors.black87,
      textStyle: TextStyle(color: Colors.white),
      borderRadius: BorderRadius.circular(8),
      mode: TooltipMode.onlyWhenOverflow,
    ),
  ),
  onChanged: (value) => setState(() => selected = value),
)

Menu Width & Alignment

FlutterDropdownButton<String>.text(
  items: items,
  width: 120,
  minMenuWidth: 250,
  maxMenuWidth: 400,
  menuAlignment: MenuAlignment.center,
  onChanged: (value) {},
)

Single-Item Mode

FlutterDropdownButton<String>.text(
  items: ['Only Option'],
  disableWhenSingleItem: true,
  hideIconWhenSingleItem: true,
  onChanged: (value) {},
)

Leading Widget

FlutterDropdownButton<String>.text(
  items: ['USD', 'EUR', 'JPY'],
  leading: Icon(Icons.attach_money, size: 20),
  selectedLeading: Icon(Icons.attach_money, size: 20, color: Colors.blue),
  leadingPadding: EdgeInsets.only(right: 12),
  onChanged: (value) {},
)

Expand in Flex Container

Row(
  children: [
    Text('Label:'),
    FlutterDropdownButton<String>.text(
      items: items,
      expand: true,
      maxWidth: 200,
      onChanged: (value) {},
    ),
  ],
)

Manual Dropdown Cleanup

void navigateToHome() {
  FlutterDropdownButton.closeAll();
  Navigator.pushNamedAndRemoveUntil(context, '/home', (route) => false);
}

Note: Dropdowns are automatically cleaned up during widget disposal. Use closeAll() only when you need explicit control.


Migration from 1.x

BasicDropdownButton → FlutterDropdownButton

// Before (1.x)
BasicDropdownButton<String>(
  items: [
    DropdownItem(value: 'apple', child: Text('Apple'), onTap: () {}),
    DropdownItem(value: 'banana', child: Text('Banana')),
  ],
  value: selected,
  hint: Text('Select'),
  onChanged: (v) {},
)

// After (2.0)
FlutterDropdownButton<String>(
  items: ['apple', 'banana'],
  value: selected,
  hintWidget: Text('Select'),
  itemBuilder: (item, isSelected) => Text(item),
  onChanged: (v) {},
)

TextOnlyDropdownButton → FlutterDropdownButton.text

// Before (1.x)
TextOnlyDropdownButton(
  items: ['A', 'B', 'C'],
  value: selected,
  hint: 'Select',
  width: 200,
  onChanged: (v) {},
)

// After (2.0)
FlutterDropdownButton<String>.text(
  items: ['A', 'B', 'C'],
  value: selected,
  hint: 'Select',
  width: 200,
  onChanged: (v) {},
)

DynamicTextBaseDropdownButton → FlutterDropdownButton.text

// Before (1.x)
DynamicTextBaseDropdownButton(
  items: items,
  value: selected,
  disableWhenSingleItem: true,
  leading: Icon(Icons.star),
  onChanged: (v) {},
)

// After (2.0)
FlutterDropdownButton<String>.text(
  items: items,
  value: selected,
  disableWhenSingleItem: true,
  leading: Icon(Icons.star),
  onChanged: (v) {},
)

Removed APIs

Removed Replacement
DropdownItem<T> itemBuilder callback
showSeparator / separator DropdownTheme.itemBorder
BasicDropdownButton.borderRadius DropdownTheme.borderRadius
BasicDropdownButton.decoration DropdownTheme.overlayDecoration
DropdownItem.onTap Handle in onChanged callback

Example

Check out the example app for a comprehensive demonstration of all features and customization options.

License

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

Changelog

See CHANGELOG.md for a detailed list of changes and version history.

About

A highly customizable dropdown package with overlay-based rendering, smooth animations, and specialized variants for different content types.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors