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

Flutter中基于JSON数据实现三级联动下拉菜单的技术求助

实现Flutter关联下拉菜单(基于Bloc和PizzaEntity)

作为Flutter初学者,我现有如下JSON响应数据:

{
   "pizza":[
      {
         "type":"auto",
         "name":"bmw",
         "currency":"usd"
      },
      {
         "type":"furniture",
         "name":"closet",
         "currency":"eur"
      },
      {
         "type":"electronics",
         "name":"PC",
         "currency":"GBP"
      },
      {
         "type":"auto",
         "name":"audi",
         "currency":"GBP"
      }
   ]
}

数据已映射至PizzaEntity实体类:

class PizzaEntity extends Equatable  {
  final String type;
  final String name;
  final String currency;
  
  const PizzaEntity({
    required this.type,
    required this.name,
    required this.currency, 
  });

  @override
  List<Object?> get props => [
        type,
        name,
        currency,
      ];
}

现有UI代码片段:

BlocBuilder<MyBlocBloc, MyBlocState>(
            builder: (context, state) {
          if (state is MyBlocLoading) {
            return const Center(
              child: CircularProgressIndicator(),
            );
          } else if (state is MyBlocLoaded) {
            // 修正:原代码类型错误,此处应为List<PizzaEntity>
            List<PizzaEntity> pizzas = state.pizza;
            if (pizzas.isEmpty) {
              return const Text("暂无数据");
            }
            
            return  // 需在此处添加三个关联下拉菜单
          } else if (state is MyBlocError) {
            return const Text("加载失败");
          } else {
            return const Center(
              child: Icon(Icons.error),
            );
          }
        }
        )

需要添加三个关联的下拉菜单:

  • 类型下拉菜单(如auto);
  • 关联选中类型的名称下拉菜单(如选中auto时显示bmw、audi);
  • 关联选中类型和名称的货币下拉菜单(如选中bmw时显示usd,选中audi时显示GBP)。

具体实现代码

将上述代码中return // 需在此处添加三个关联下拉菜单的位置替换为以下代码,通过StatefulBuilder管理临时选中状态实现下拉联动:

return StatefulBuilder(
  builder: (context, setState) {
    String? selectedType;
    String? selectedName;
    String? selectedCurrency;

    // 获取去重的所有类型选项
    final types = pizzas.map((e) => e.type).toSet().toList();
    // 根据选中类型过滤名称选项
    final names = selectedType != null 
        ? pizzas.where((e) => e.type == selectedType).map((e) => e.name).toSet().toList()
        : [];
    // 根据选中类型和名称过滤货币选项
    final currencies = selectedType != null && selectedName != null
        ? pizzas.where((e) => e.type == selectedType && e.name == selectedName).map((e) => e.currency).toSet().toList()
        : [];

    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        // 类型下拉菜单
        DropdownButton<String>(
          hint: const Text("选择类型"),
          value: selectedType,
          items: types.map((type) {
            return DropdownMenuItem(
              value: type,
              child: Text(type),
            );
          }).toList(),
          onChanged: (value) {
            setState(() {
              selectedType = value;
              // 切换类型时重置名称和货币选中值
              selectedName = null;
              selectedCurrency = null;
            });
          },
        ),
        const SizedBox(height: 16),
        // 名称下拉菜单(关联类型)
        DropdownButton<String>(
          hint: const Text("选择名称"),
          value: selectedName,
          items: names.map((name) {
            return DropdownMenuItem(
              value: name,
              child: Text(name),
            );
          }).toList(),
          onChanged: selectedType != null 
              ? (value) {
                  setState(() {
                    selectedName = value;
                    // 切换名称时重置货币选中值
                    selectedCurrency = null;
                  });
                }
              : null,
          enabled: selectedType != null,
        ),
        const SizedBox(height: 16),
        // 货币下拉菜单(关联类型和名称)
        DropdownButton<String>(
          hint: const Text("选择货币"),
          value: selectedCurrency,
          items: currencies.map((currency) {
            return DropdownMenuItem(
              value: currency,
              child: Text(currency),
            );
          }).toList(),
          onChanged: (selectedType != null && selectedName != null)
              ? (value) {
                  setState(() {
                    selectedCurrency = value;
                  });
                }
              : null,
          enabled: selectedType != null && selectedName != null,
        ),
      ],
    );
  },
);

代码说明

  1. 状态管理:用StatefulBuilder在BlocBuilder内部临时维护下拉选中状态,避免把UI临时状态混入Bloc全局状态(若需全局保存选中值,可将状态移入Bloc)。
  2. 选项过滤:
    • 类型选项:从所有实体中提取去重的type;
    • 名称选项:根据选中的type过滤对应name并去重;
    • 货币选项:根据选中的type和name过滤对应currency;
  3. 联动逻辑:切换类型时重置名称和货币选中值,切换名称时重置货币选中值,确保下拉选项始终与当前选中状态匹配。

内容的提问来源于stack exchange,提问作者Leilin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 11:05:23