Flutter:不支持空安全的flutter_tags组件替代方案及等效代码实现
替代方案推荐与代码实现
推荐方案
直接用Flutter自带的Wrap+Chip组件,无需依赖第三方包,天然支持空安全,性能更稳定。如果偏好类似旧版flutter_tags的API风格,也可以用适配了空安全的flutter_tagging包。
官方组件实现(完全匹配原功能)
先预处理去重后的标签列表,避免在build流程里重复做判断:
// 提前获取去重后的标签列表,按iGRPCODE去重 List<Items> get _uniqueNewArrivalsItems { final Set<String> seenCodes = {}; return _newArrivalsItems.where((item) { if (seenCodes.contains(item.iGRPCODE)) return false; seenCodes.add(item.iGRPCODE); return true; }).toList(); } Widget _buildFilter() { return Wrap( spacing: 5, runSpacing: 5, children: _uniqueNewArrivalsItems.map((obj) { final isSelected = _selectedNewArrivalsItemCodes.contains(obj.iGRPCODE); return Chip( label: Text(obj.iGRPDESC), // 模拟原active属性的选中样式,可按需调整 backgroundColor: isSelected ? Colors.blue[100] : null, deleteIcon: const Icon(Icons.close), onDeleted: () { setState(() { _selectedNewArrivalsItemCodes.remove(obj.iGRPCODE); }); }, onPressed: () { setState(() { if (_selectedNewArrivalsItemCodes.contains(obj.iGRPCODE)) { _selectedNewArrivalsItemCodes.remove(obj.iGRPCODE); } else { _selectedNewArrivalsItemCodes.add(obj.iGRPCODE); } }); }, onLongPress: () => print(obj), ); }).toList(), ); }
代码说明
- 去重优化:把原代码里在itemBuilder里的去重逻辑提到外部,避免build时重复创建空Container,提升性能
- 选中状态:通过
isSelected判断标签是否被选中,动态调整背景色对应原active属性 - 删除功能:用Chip自带的
deleteIcon和onDeleted实现原ItemTagsRemoveButton的效果 - 点击切换:和原代码逻辑完全一致,点击标签切换选中/取消选中状态
- 长按功能:通过
onLongPress实现原长按打印标签的需求
第三方包flutter_tagging实现
如果习惯类似旧版的API风格,可使用flutter_tagging包,代码如下:
import 'package:flutter_tagging/flutter_tagging.dart'; Widget _buildFilter() { final uniqueItems = _uniqueNewArrivalsItems; // 复用上面的去重方法 return FlutterTagging<Items>( initialItems: _selectedNewArrivalsItems, textFieldConfiguration: const TextFieldConfiguration( enabled: false, // 隐藏输入框,只展示标签 ), findSuggestions: (String query) async => uniqueItems, additionCallback: (value) => Items(iGRPCODE: '', iGRPDESC: value), onAdded: (item) => _selectedNewArrivalsItemCodes.add(item.iGRPCODE), onRemoved: (item) => _selectedNewArrivalsItemCodes.remove(item.iGRPCODE), itemBuilder: (context, item, index) { final isSelected = _selectedNewArrivalsItemCodes.contains(item.iGRPCODE); return Chip( label: Text(item.iGRPDESC), backgroundColor: isSelected ? Colors.blue[100] : null, onPressed: () { setState(() { isSelected ? _selectedNewArrivalsItemCodes.remove(item.iGRPCODE) : _selectedNewArrivalsItemCodes.add(item.iGRPCODE); }); }, onLongPress: () => print(item), ); }, ); }
内容的提问来源于stack exchange,提问作者mohamed sakir
相关产品推荐
相关产品推荐

