import 'package:flutter/material.dart'; /// 数据转换函数签名 /// 将原始数据转换为SelectOption类型的函数 typedef SelectOptionConverter = SelectOption Function(T data); /// 选择器选项数据模型 class SelectOption { final String label; final String value; final dynamic extra; SelectOption({required this.label, required this.value, this.extra}); } /// 通用选择器组件 /// 支持静态数据源和动态API数据源 class VberSelect extends StatefulWidget { /// 静态数据列表 final List? items; /// API获取数据的方法 final Future> Function()? fetchData; /// 数据转换方法,将原始数据转换为SelectOption final SelectOptionConverter converter; /// 当前选中的值 final String? value; /// 值改变回调 final Function(String?)? onChanged; /// 提示文字 final String? hint; /// 是否启用 final bool enabled; /// 是否显示"全部"选项 final bool showAll; /// 是否隐藏下划线 final bool hideUnderline; /// 是否显示清空按钮 final bool showClearButton; const VberSelect({ super.key, this.items, this.fetchData, required this.converter, this.value, this.onChanged, this.hint, this.enabled = true, this.showAll = false, this.hideUnderline = false, this.showClearButton = false, }); @override State> createState() => _VberSelectState(); } class _VberSelectState extends State> { List? _items; bool _loading = false; String? _selectedValue; @override void initState() { super.initState(); _selectedValue = widget.value; // 使用WidgetsBinding.instance.addPostFrameCallback确保在widget构建完成后再加载数据 WidgetsBinding.instance.addPostFrameCallback((_) { _loadData(); }); } @override void didUpdateWidget(covariant VberSelect oldWidget) { super.didUpdateWidget(oldWidget); // 当外部传入的value发生变化时,同步更新内部状态 if (oldWidget.value != widget.value) { setState(() { _selectedValue = widget.value; }); } } Future _loadData() async { // 如果提供了fetchData方法,则优先使用它获取数据 if (widget.fetchData != null) { // 使用Future.microtask确保在下一个微任务中加载数据,避免在构建过程中修改状态 Future.microtask(() async { setState(() { _loading = true; }); try { final data = await widget.fetchData!(); setState(() { _items = data; _loading = false; }); } catch (e) { setState(() { _loading = false; }); } }); } else { // 否则使用传入的静态数据 setState(() { _items = widget.items; }); } } @override Widget build(BuildContext context) { if (_loading) { Widget dropdownWidget = DropdownButton( items: [], hint: SizedBox( width: 16, height: 16, child: CircularProgressIndicator(strokeWidth: 2), ), onChanged: (String? value) {}, ); Widget selectWidget = widget.hideUnderline ? DropdownButtonHideUnderline(child: dropdownWidget) : dropdownWidget; if (widget.showClearButton) { return Row( children: [ Expanded(child: selectWidget), IconButton( icon: const Icon(Icons.clear, size: 20), onPressed: widget.enabled ? () { setState(() { _selectedValue = null; }); widget.onChanged?.call(null); } : null, ), ], ); } return selectWidget; } // 构建最终的下拉选项列表 List> dropdownItems = []; // 如果showAll为true,添加"全部"选项 if (widget.showAll) { dropdownItems.add(DropdownMenuItem(value: '', child: Text('全部'))); } // 只有当_items不为null且不为空时才添加实际选项 if (_items != null && _items!.isNotEmpty) { final options = _items!.map((item) => widget.converter(item)).toList(); // 添加转换后的选项 dropdownItems.addAll( options.map((option) { return DropdownMenuItem( value: option.value, child: Text(option.label), ); }).toList(), ); } Widget dropdownWidget = DropdownButton( value: _selectedValue, hint: Text(widget.hint ?? '请选择'), items: dropdownItems, onChanged: widget.enabled ? (String? newValue) { setState(() { _selectedValue = newValue; }); widget.onChanged?.call(newValue); } : null, isExpanded: true, ); Widget selectWidget = widget.hideUnderline ? DropdownButtonHideUnderline(child: dropdownWidget) : dropdownWidget; if (widget.showClearButton) { return Row( children: [ Expanded(child: selectWidget), IconButton( icon: const Icon(Icons.clear, size: 20), onPressed: widget.enabled ? () { setState(() { _selectedValue = null; }); widget.onChanged?.call(null); } : null, ), ], ); } return selectWidget; } }