You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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(),
  );
}

代码说明

  1. 去重优化:把原代码里在itemBuilder里的去重逻辑提到外部,避免build时重复创建空Container,提升性能
  2. 选中状态:通过isSelected判断标签是否被选中,动态调整背景色对应原active属性
  3. 删除功能:用Chip自带的deleteIcon和onDeleted实现原ItemTagsRemoveButton的效果
  4. 点击切换:和原代码逻辑完全一致,点击标签切换选中/取消选中状态
  5. 长按功能:通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 14:54:59