FilteredMenu<T> class
A searchable dropdown menu with keyboard navigation and text filtering.
FilteredMenu combines a text field with a dropdown menu, allowing users to search through options by typing. As the user types, the menu filters to show only matching items. Perfect for large lists where users need to quickly find specific options.
Features
- Live Search: Filter menu items as you type
- Keyboard Navigation: Use arrow keys to navigate, Enter to select, Escape to close
- Auto-Highlighting: Automatically highlights the first matching item
- Visual Feedback: Highlights current selection and keyboard-focused items
- Customizable Size: Adjustable height, width, and cursor height
Quick Start
FilteredMenu<String>(
items: [
MenuItem(label: 'Apple', value: 'apple'),
MenuItem(label: 'Banana', value: 'banana'),
MenuItem(label: 'Cherry', value: 'cherry'),
],
setStateCallback: () => setState(() {}),
label: 'Select Fruit',
onSelected: (value) {
print('Selected: $value');
},
)
Constructor Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
items |
List<MenuItem> |
Yes | List of menu items to display |
setStateCallback |
VoidCallback |
Yes | Callback to trigger parent widget rebuild |
initialSelection |
T? |
No | Value to pre-select when widget loads |
onSelected |
ValueChanged<T?>? |
No | Callback when user selects an item |
height |
double? |
No | Height of the text field (default: 40) |
width |
double? |
No | Width of the text field and dropdown |
label |
String? |
No | Label text displayed above the field |
keyboardType |
TextInputType? |
No | Keyboard type for the text field |
cursorHeight |
double? |
No | Height of the text cursor |
Keyboard Shortcuts
- Arrow Down: Move to next item
- Arrow Up: Move to previous item
- Enter: Select highlighted item
- Escape: Close the dropdown
Filtering Behavior
The menu filters items using case-insensitive substring matching. When you type:
- Items containing the search text anywhere in their label are shown
- The first item starting with the search text is automatically highlighted
- The dropdown scrolls to keep the highlighted item visible
Example with Custom Sizing
FilteredMenu<int>(
items: List.generate(
100,
(i) => MenuItem(label: 'Option ${i + 1}', value: i),
),
setStateCallback: () => setState(() {}),
height: 50,
width: 300,
cursorHeight: 24,
label: 'Pick a Number',
initialSelection: 42,
onSelected: (value) {
print('You picked: $value');
},
)
Example with Custom Types
class Product {
final String name;
final double price;
Product(this.name, this.price);
}
FilteredMenu<Product>(
items: [
MenuItem(label: 'Laptop', value: Product('Laptop', 999.99)),
MenuItem(label: 'Mouse', value: Product('Mouse', 29.99)),
MenuItem(label: 'Keyboard', value: Product('Keyboard', 79.99)),
],
setStateCallback: () => setState(() {}),
onSelected: (product) {
if (product != null) {
print('${product.name}: \$${product.price}');
}
},
)
See Also
- SimpleMenu - A basic dropdown without search functionality
- SuggestionField - Text field with dropdown suggestions
- MenuItem - Individual menu item data structure
- Inheritance
-
- Object
- DiagnosticableTree
- Widget
- StatefulWidget
- FilteredMenu
- Available extensions
Constructors
-
FilteredMenu({Key? key, required List<
MenuItem> items, required VoidCallback setStateCallback, String label = '', T? initialSelection, ValueChanged<T?> ? onSelected, double? height = 30, double? width = 200, TextInputType? keyboardType, double? cursorHeight, BoxDecoration decoration = const BoxDecoration(), InputDecoration inputDecoration = const InputDecoration()}) -
const
Properties
- cursorHeight → double?
-
final
- decoration → BoxDecoration
-
final
- hashCode → int
-
The hash code for this object.
no setterinherited
- height → double?
-
final
- initialSelection → T?
-
final
- inputDecoration → InputDecoration
-
final
-
items
→ List<
MenuItem> -
final
- key → Key?
-
Controls how one widget replaces another widget in the tree.
finalinherited
- keyboardType → TextInputType?
-
final
- label → String
-
final
- makeRefreshable → Widget
-
Available on Widget?, provided by the WidgetExtension extension
Make your any widget refreshable with RefreshIndicator on topno setter -
onSelected
→ ValueChanged<
T?> ? -
final
- runtimeType → Type
-
A representation of the runtime type of the object.
no setterinherited
- setStateCallback → VoidCallback
-
final
- width → double?
-
final
Methods
-
center(
{double? heightFactor, double? widthFactor}) → Widget -
Available on Widget?, provided by the WidgetExtension extension
set parent widget in center -
cornerRadiusWithClipRRect(
double radius) → ClipRRect -
Available on Widget?, provided by the WidgetExtension extension
add corner radius -
cornerRadiusWithClipRRectOnly(
{int bottomLeft = 0, int bottomRight = 0, int topLeft = 0, int topRight = 0}) → ClipRRect -
Available on Widget?, provided by the WidgetExtension extension
add custom corner radius each side -
createElement(
) → StatefulElement -
Creates a StatefulElement to manage this widget's location in the tree.
inherited
-
createState(
) → State< FilteredMenu< T> > -
Creates the mutable state for this widget at a given location in the tree.
override
-
debugDescribeChildren(
) → List< DiagnosticsNode> -
Returns a list of DiagnosticsNode objects describing this node's
children.
inherited
-
debugFillProperties(
DiagnosticPropertiesBuilder properties) → void -
Add additional properties associated with the node.
inherited
-
expand(
{int flex = 1}) → Widget -
Available on Widget?, provided by the WidgetExtension extension
add Expanded to parent widget -
fit(
{BoxFit? fit, AlignmentGeometry? alignment}) → Widget -
Available on Widget?, provided by the WidgetExtension extension
add FittedBox to parent widget -
flexible(
{int flex = 1, FlexFit? fit}) → Widget -
Available on Widget?, provided by the WidgetExtension extension
add Flexible to parent widget -
noSuchMethod(
Invocation invocation) → dynamic -
Invoked when a nonexistent method or property is accessed.
inherited
-
opacity(
{required double opacity, int durationInSecond = 1, Duration? duration}) → Widget -
Available on Widget?, provided by the WidgetExtension extension
add opacity to parent widget -
paddingAll(
double padding) → Padding -
Available on Widget?, provided by the WidgetExtension extension
return padding all -
paddingBottom(
double bottom) → Padding -
Available on Widget?, provided by the WidgetExtension extension
return padding bottom -
paddingDirectional(
{double start = 0.0, double top = 0.0, double end = 0.0, double bottom = 0.0}) → Widget -
Available on Widget?, provided by the WidgetExtension extension
-
paddingLeft(
double left) → Padding -
Available on Widget?, provided by the WidgetExtension extension
return padding left -
paddingOnly(
{double top = 0.0, double left = 0.0, double bottom = 0.0, double right = 0.0}) → Padding -
Available on Widget?, provided by the WidgetExtension extension
return custom padding from each side -
paddingRight(
double right) → Padding -
Available on Widget?, provided by the WidgetExtension extension
return padding right -
paddingSymmetric(
{double vertical = 0.0, double horizontal = 0.0}) → Padding -
Available on Widget?, provided by the WidgetExtension extension
return padding symmetric -
paddingTop(
double top) → Padding -
Available on Widget?, provided by the WidgetExtension extension
return padding top -
rotate(
{required double angle, bool transformHitTests = true, Offset? origin}) → Widget -
Available on Widget?, provided by the WidgetExtension extension
add rotation to parent widget -
scale(
{required double scale, Offset? origin, AlignmentGeometry? alignment, bool transformHitTests = true}) → Widget -
Available on Widget?, provided by the WidgetExtension extension
add scaling to parent widget -
toDiagnosticsNode(
{String? name, DiagnosticsTreeStyle? style}) → DiagnosticsNode -
Returns a debug representation of the object that is used by debugging
tools and by DiagnosticsNode.toStringDeep.
inherited
-
tooltip(
{required String msg}) → Widget -
Available on Widget?, provided by the WidgetExtension extension
-
toString(
{DiagnosticLevel minLevel = DiagnosticLevel.info}) → String -
A string representation of this object.
inherited
-
toStringDeep(
{String prefixLineOne = '', String? prefixOtherLines, DiagnosticLevel minLevel = DiagnosticLevel.debug, int wrapWidth = 65}) → String -
Returns a string representation of this node and its descendants.
inherited
-
toStringShallow(
{String joiner = ', ', DiagnosticLevel minLevel = DiagnosticLevel.debug}) → String -
Returns a one-line detailed description of the object.
inherited
-
toStringShort(
) → String -
A short, textual description of this widget.
inherited
-
translate(
{required Offset offset, bool transformHitTests = true, Key? key}) → Widget -
Available on Widget?, provided by the WidgetExtension extension
add translate to parent widget -
validate(
{Widget value = const SizedBox()}) → Widget -
Available on Widget?, provided by the WidgetExtension extension
Validate given widget is not null and returns given value if null. -
visible(
bool visible, {Widget? defaultWidget}) → Widget -
Available on Widget?, provided by the WidgetExtension extension
set visibility -
withHeight(
double height) → SizedBox -
Available on Widget?, provided by the WidgetExtension extension
With custom height -
withShaderMask(
List< Color> colors, {BlendMode blendMode = BlendMode.srcATop}) → Widget -
Available on Widget?, provided by the WidgetExtension extension
Wrap with ShaderMask widget -
withShaderMaskGradient(
Gradient gradient, {BlendMode blendMode = BlendMode.srcATop}) → Widget -
Available on Widget?, provided by the WidgetExtension extension
Wrap with ShaderMask widget Gradient -
withSize(
{double width = 0.0, double height = 0.0}) → SizedBox -
Available on Widget?, provided by the WidgetExtension extension
With custom height and width -
withTooltip(
{required String msg}) → Widget -
Available on Widget?, provided by the WidgetExtension extension
Validate given widget is not null and returns given value if null. -
withVisibility(
bool visible, {Widget? replacement, bool maintainAnimation = false, bool maintainState = false, bool maintainSize = false, bool maintainSemantics = false, bool maintainInteractivity = false}) → Visibility -
Available on Widget?, provided by the WidgetExtension extension
set widget visibility -
withWidth(
double width) → SizedBox -
Available on Widget?, provided by the WidgetExtension extension
With custom width
Operators
-
operator ==(
Object other) → bool -
The equality operator.
inherited