Flutter DropdownSearch
Flutter 简单且健壮的 DropdownSearch,带有关项目搜索功能,可以使用离线项目列表或过滤 URL 进行轻松定制。

主要特点
- 在线和离线项目
- 可搜索下拉框
- 三种下拉模式:菜单/底部工作表/对话框
- Material 下拉框
- 易于定制的 UI
- 处理浅色和深色主题
- 在 StatelessWidget 中轻松实现

packages.yaml
dropdown_search: <lastest version>
导入
import 'package:dropdown_search/dropdown_search.dart';
简单实现
DropdownSearch<String>(
mode: Mode.MENU,
showSelectedItem: true,
items: ["Brazil", "Italia (Disabled)", "Tunisia", 'Canada'],
label: "Menu mode",
hint: "country in menu mode",
popupItemDisabled: (String s) => s.startsWith('I'),
onChanged: print,
selectedItem: "Brazil"),
自定义显示字段 (itemAsString)
DropdownSearch<UserModel>(
label: "Name",
onFind: (String filter) => getData(filter),
itemAsString: (UserModel u) => u.userAsStringByName(),
onChanged: (UserModel data) => print(data),
),
DropdownSearch<UserModel>(
label: "Name",
onFind: (String filter) => getData(filter),
itemAsString: (UserModel u) => u.userAsStringById(),
onChanged: (UserModel data) => print(data),
),
自定义过滤函数
DropdownSearch<UserModel>(
label: "Name",
filterFn: (user, filter) => user.userFilterByCreationDate(filter),
onFind: (String filter) => getData(filter),
itemAsString: (UserModel u) => u.userAsStringByName(),
onChanged: (UserModel data) => print(data),
),
自定义搜索模式
DropdownSearch<UserModel>(
mode: Mode.BOTTOM_SHEET,
label: "Name",
onFind: (String filter) => getData(filter),
itemAsString: (UserModel u) => u.userAsString(),
onChanged: (UserModel data) => print(data),
),
验证
DropdownSearch(
items: ["Brazil", "France", "Tunisia", "Canada"],
label: "Country",
onChanged: print,
selectedItem: "Tunisia",
validator: (String item) {
if (item == null)
return "Required field";
else if (item == "Brazil")
return "Invalid item";
else
return null;
},
);
端点实现(使用 Dio 包)
DropdownSearch<UserModel>(
label: "Name",
onFind: (String filter) async {
var response = await Dio().get(
"http://5d85ccfb1e61af001471bf60.mockapi.io/user",
queryParameters: {"filter": filter},
);
var models = UserModel.fromJsonList(response.data);
return models;
},
onChanged: (UserModel data) {
print(data);
},
);
布局定制
您可以自定义 DropdownSearch 及其项目的布局。 示例
| 属性 | 描述 |
|---|---|
label |
DropdownSearch 标签 |
showSearchBox |
显示/隐藏搜索框 |
isFilteredOnline |
如果项目过滤是在线进行的(通过 API),则为 true |
showClearButton |
显示/隐藏清除已选项目 |
items |
离线项目列表 |
selectedItem |
已选项目 |
onFind |
返回 API 中项目的函数 |
onChanged |
当选择新项目时调用 |
dropdownBuilder |
用于自定义项目列表 UI |
popupItemBuilder |
用于自定义已选项目 |
validator |
应用验证公式的函数 |
searchBoxDecoration |
搜索框的装饰 |
popupBackgroundColor |
对话框/菜单/底部工作表的背景颜色 |
popupTitle |
弹出窗口标题的自定义小部件 |
itemAsString |
自定义要显示的字段 |
filterFn |
自定义过滤函数 |
enabled |
启用/禁用 dropdownSearch |
mode |
菜单/对话框/底部工作表 |
maxHeight |
对话框/底部工作表/菜单的最大高度 |
dialogMaxWidth |
对话框的最大宽度 |
showSelectedItem |
管理已选项目的可见性(如果为 true,则已选项目将高亮显示) |
compareFn |
Function(T item, T selectedItem),自定义比较函数 |
dropdownSearchDecoration |
DropdownSearch 输入装饰 |
emptyBuilder |
空结果的自定义布局 |
loadingBuilder |
加载项目的自定义布局 |
errorBuilder |
错误的自定义布局 |
autoFocusSearchBox |
如果为 true,则搜索框将被聚焦 |
popupShape |
弹出窗口的自定义形状 |
autoValidateMode |
处理自动验证模式 |
onSaved |
保存表单时可用于最终值的可选方法(通过 |
validator |
一个可选方法,用于验证输入。如果输入无效,则返回一个要显示的错误字符串,否则返回 null。 |
clearButton |
自定义清除按钮小部件 |
dropDownButton |
自定义下拉按钮小部件 |
dropdownBuilderSupportsNullItem |
如果为 true,则 dropdownBuilder 将继续使用 Material 的行为。如果您只想在 item !=null 时处理自定义 UI,这将非常有用 |
popupItemDisabled |
定义弹出窗口中的项目是否可用,如果项目不可用,则无法单击 |
popupBarrierColor |
为弹出窗口屏障设置自定义颜色 |
searchBoxController |
搜索框控制器 |
clearButtonBuilder |
自定义清除按钮构建器 |
dropdownButtonBuilder |
自定义下拉按钮构建器 |
onBeforeChange |
在应用值更改之前执行的回调 |
searchDelay |
搜索前的延迟 |
注意
要将模板用作项目类型,并且您不想使用自定义函数 **itemAsString** 和 **compareFn**,您**需要**实现 **toString**、**equals** 和 **hashcode**,如下所示
class UserModel {
final String id;
final DateTime createdAt;
final String name;
final String avatar;
UserModel({this.id, this.createdAt, this.name, this.avatar});
factory UserModel.fromJson(Map<String, dynamic> json) {
if (json == null) return null;
return UserModel(
id: json["id"],
createdAt:
json["createdAt"] == null ? null : DateTime.parse(json["createdAt"]),
name: json["name"],
avatar: json["avatar"],
);
}
static List<UserModel> fromJsonList(List list) {
if (list == null) return null;
return list.map((item) => UserModel.fromJson(item)).toList();
}
///this method will prevent the override of toString
String userAsString() {
return '#${this.id} ${this.name}';
}
///this method will prevent the override of toString
bool userFilterByCreationDate(String filter) {
return this?.createdAt?.toString()?.contains(filter);
}
///custom comparing function to check if two users are equal
bool isEqual(UserModel model) {
return this?.id == model?.id;
}
@override
String toString() => name;
}