I have a dropdown button which I implemented using dropdown_button2 1.9.2
.
I want to make the dropdown_button searchable.
I tried implementing it with my custom class but it won't work.
I have tried overriding the toString method
of my class (as suggested in this answer) but it still won't work.
Please any fix or am I doing something wrong here?
This is the dropdown button
This is what it does when I try searching for an item in the dropdown.
This is my full code:
import 'package:dropdown_button2/dropdown_button2.dart';
import 'package:flutter/material.dart';
// ignore_for_file: public_member_api_docs, sort_constructors_first
class MyDropDownItems {
MyDropDownItems({
required this.text,
required this.value,
});
String text;
String value;
@override
String toString() {
return value;
}
}
class MoodScreen extends StatefulWidget {
const MoodScreen({super.key});
@override
State<MoodScreen> createState() => _MoodScreenState();
}
class _MoodScreenState extends State<MoodScreen> {
final TextEditingController _textEditingController = TextEditingController();
// Initial Selected Value
String _dropdownvalue = ' ';
final _dropDownItems = [
MyDropDownItems(text: "Select Mood", value: " "),
MyDropDownItems(text: "Mood 1", value: "happy"),
MyDropDownItems(text: "Mood 2", value: "Sad"),
MyDropDownItems(text: "Mood 3", value: "Confused"),
MyDropDownItems(text: "Mood 4", value: "Lonely"),
MyDropDownItems(text: "Mood 5", value: "Excited"),
MyDropDownItems(text: "Mood 6", value: "Wealthy"),
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: 300,
padding: const EdgeInsets.symmetric(
horizontal: 12,
vertical: 4,
),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
border: Border.all(color: Colors.green, width: 4),
),
child: DropdownButtonHideUnderline(
child: DropdownButton2(
searchController: _textEditingController,
searchInnerWidget: Padding(
padding: const EdgeInsets.only(
top: 8,
bottom: 4,
right: 8,
left: 8,
),
child: TextFormField(
controller: _textEditingController,
decoration: const InputDecoration(
isDense: true,
hintText: 'Select mood...',
contentPadding: EdgeInsets.symmetric(
horizontal: 10,
vertical: 8,
),
),
),
),
searchMatchFn: (item, searchValue) {
return (item.value.toString().contains(searchValue));
},
onMenuStateChange: (isOpen) {
if (!isOpen) {
_textEditingController.clear();
}
},
value: _dropdownvalue,
isExpanded: true,
iconSize: 36,
iconEnabledColor: Colors.green,
icon: const Icon(
Icons.arrow_drop_down_circle,
),
items: _dropDownItems.map((MyDropDownItems networkNumbers) {
return DropdownMenuItem(
value: networkNumbers.value,
child: Text(networkNumbers.text),
);
}).toList(),
onChanged: (value) {
setState(() {
_dropdownvalue = value!;
});
},
),
),
),
const SizedBox(height: 20),
Text("The mood is: $_dropdownvalue"),
],
),
),
);
}
}
If you really want to search by the display name, then searchMatchFn
should be as following
searchMatchFn: (item, searchValue) {
final myItem = _dropDownItems.firstWhere((element) => element.value == item.value);
return myItem.text.contains(searchValue);
}
or if you need search based on value and text, then
searchMatchFn: (item, searchValue) {
final myItem = _dropDownItems.firstWhere((element) => element.value == item.value);
return myItem.text.contains(searchValue) || item.value.toString().contains(searchValue);
}