flutter下拉框组件
实现下拉框效果
DropdownButton
flutter自带的组件
Expanded(
child: DropdownButton<
String>(
isExpanded:true,
value: _therapistsId,
items: _therapists.map((e) => DropdownMenuItem(value: e.therapistId,child: Text(e.therapistName))).toList(),
onChanged: (e) {
if (e is String) {
setState(() {
_therapistsId = e;
///...
});
}
})),
插件 dropdown_search
单选
import 'package:flutter/material.dart';
import 'package:dropdown_search/dropdown_search.dart';
import './drop_down_type.dart';
class DropDownSingle extends StatelessWidget {
const DropDownSingle(
{super.key,
required this.options,
required this.value,
required this.onChanged});
final List<DropDownType> options;
final String value;
final ValueChanged<String> onChanged;
Widget build(BuildContext context) {
return DropdownSearch(
items: options.map((e) => e.k).toList(),
selectedItem: options.where((f) => f.v == value).toList().isNotEmpty
? options.where((f) => f.v == value).toList()[0].k
: '',
onChanged: (value) {
var list = options.where((f) => f.k == value).toList();
if (list.isNotEmpty) {
onChanged(list[0].v);
}
},
popupProps: PopupProps.menu(
constraints: BoxConstraints(
maxHeight: options.length < 5 ? options.length * 58 : 5 * 58)),/// 下拉框的长度修改
);
}
}
类型
class DropDownType {
DropDownType({
required this.k,
required this.v,
});
final String k;
final String v;
}
使用:
Expanded(
child: DropDownSingle(options: _therapists.map((e) => DropDownType(k: e.therapistName,v: e.therapistId)).toList(),
value:_therapistsId ??"",
onChanged: (e) {
setState(() {
_therapistsId = e;
///
});
}),
)
多选:
import 'package:dropdown_search/dropdown_search.dart';
import 'package:flutter/material.dart';
import 'package:rehab_therapist/components/form_widget/drop_down_type.dart';
class DropDownMulti extends StatelessWidget {
const DropDownMulti(
{super.key,
required this.options,
required this.value,
required this.onChanged});
final List<DropDownType> options;
final List<String> value;
final ValueChanged<List<String>> onChanged;
Widget build(BuildContext context) {
return DropdownSearch.multiSelection(
clearButtonProps: const ClearButtonProps(isVisible: true),
items: options.map((e) => e.k).toList(),
selectedItems: options
.where((f) => value.contains(f.v))
.toList()
.map((e) => e.k)
.toList(),
onChanged: (value) {
var list = options
.where((f) => value.contains(f.k))
.toList()
.map((e) => e.v)
.toList();
onChanged(list);
},
);
}
}
上述使用方法与单选下拉类似
实现多选下拉框
组件:
/// @description: 多选下拉组件
import 'package:flutter/material.dart';
class SelectOption {
SelectOption({required this.value, required this.label});
String label;
dynamic value;
}
class MultiSelectDropdownButton extends StatefulWidget {
final String labelText;
final List<SelectOption> items;
final List<dynamic> selectedItems;
final ValueChanged<List<dynamic>> onChanged;
// ignore: prefer_const_constructors_in_immutables
MultiSelectDropdownButton({
super.key,
required this.labelText,
required this.items,
required this.selectedItems,
required this.onChanged,
});
// ignore: library_private_types_in_public_api
_MultiSelectDropdownButtonState createState() =>
_MultiSelectDropdownButtonState();
}
class _MultiSelectDropdownButtonState extends State<MultiSelectDropdownButton> {
final List<dynamic> _selectedItems = [];
final List<String> _selectedLables = [];
void initState() {
super.initState();
_selectedItems.addAll(widget.selectedItems);
for (var item in _selectedItems) {
for (var e in widget.items) {
if (e.value == item) _selectedLables.add(e.label);
}
}
}
Widget build(BuildContext context) {
return Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(widget.labelText),
PopupMenuButton(
itemBuilder: (BuildContext context) {
return widget.items.map((SelectOption e) {
return CheckedPopupMenuItem(
value: e.value,
checked: _selectedItems.contains(e.value),
child: Text(e.label),
);
}).toList();
},
onSelected: (item) {
setState(() {
if (_selectedItems.contains(item)) {
_selectedItems.remove(item);
for (var e in widget.items) {
if (e.value == item) _selectedLables.remove(e.label);
}
} else {
_selectedItems.add(item);
_selectedItems.sort();
for (var e in widget.items) {
if (e.value == item) {
_selectedLables.insert(
_selectedItems.indexOf(item), e.label);
}
}
}
widget.onChanged(_selectedItems);
});
},
child: Container(
alignment: Alignment.centerLeft,
decoration: BoxDecoration(
border: Border.all(),
borderRadius: BorderRadius.circular(4.0),
),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Text(_selectedLables.join(', ')),
),
),
),
],
);
}
}
使用:
Expanded(
flex: 1,
child: SizedBox(
height: 30,
child: ListView(
scrollDirection:
Axis.horizontal,
children: [
MultiSelectDropdownButton(
labelText: '',
items: [
SelectOption(
value: "肩",
label: "肩"),
SelectOption(
value: "肘",
label: "肘"),
SelectOption(
value: "腕",
label: "腕"),
SelectOption(
value: "髋",
label: "髋"),
SelectOption(
value: "膝",
label: "膝"),
SelectOption(
value: "踝",
label: "踝"),
SelectOption(
value: "脊柱",
label: "脊柱"),
SelectOption(
value: "其他",
label: "其他"),
],
selectedItems:
_injureBase,
onChanged:
(List<dynamic>
value) {
Future.delayed(
const Duration(
milliseconds:
1), () {
FocusScope.of(
context)
.unfocus();
});
setState(() {
_injureBase = value;
});
if (value
.contains("其他")) {
setState(() {
_showinjureOthersPart =
true;
});
} else {
setState(() {
_showinjureOthersPart =
false;
});
_userTypeController
.text = "";
}
})
],
),
)),
如果多选下拉框要修改“ok”,则如下:
import 'package:dropdown_search/dropdown_search.dart';
import 'package:flutter/material.dart';
import 'package:rehab_therapist/components/form_widget/drop_down_type.dart';
class DropDownMulti extends StatelessWidget {
const DropDownMulti(
{super.key,
required this.options,
required this.value,
required this.onChanged});
final List<DropDownType> options;
final List<String> value;
final ValueChanged<List<String>> onChanged;
Widget build(BuildContext context) {
final popupCustomValidationKey = GlobalKey<DropdownSearchState<dynamic>>();
return DropdownSearch.multiSelection(
key: popupCustomValidationKey,
clearButtonProps: const ClearButtonProps(isVisible: true),
items: options.map((e) => e.k).toList(),
selectedItems: options
.where((f) => value.contains(f.v))
.toList()
.map((e) => e.k)
.toList(),
onChanged: (value) {
var list = options
.where((f) => value.contains(f.k))
.toList()
.map((e) => e.v)
.toList();
onChanged(list);
},
popupProps: PopupPropsMultiSelection.menu(
validationWidgetBuilder: (context, selectedItems) => Container(
padding: const EdgeInsets.only(right: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
ElevatedButton(
onPressed: () {
popupCustomValidationKey.currentState
?.popupValidate(selectedItems);
},
child: const Text("确定"))
],
),
)),
);
}
}