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

基于给定Dart List实现分组下拉列表及动态依赖下拉功能

Flutter 实现分组联动下拉列表

数据预处理

先基于给定的category123数据,后续会按department字段做分组处理:

List<Map<String, dynamic>> category123 = [
    {
      "name": "Python",
      "department": "second-choice",
      "detail": ['11', '12', '13', '14'],
    },
    {
      "name": "Javascript",
      "department": "first-choice",
      "detail": ['21', '22', '23', '24'],
    },
    {
      "name": "PHP",
       "department": "first-choice",
      "detail": ['31', '32', '33', '34'],
    },
    {
      "name": "C#",
          "department": "second-choice",
      "detail": ['41', '42', '43', '44'],
    },
    {
      "name": "Java",
           "department": "first-choice",
      "detail": ['51', '52', '53', '54'],
    },
    {
      "name": "C++",
          "department": "second-choice",
      "detail": ['61', '62', '63', '64'],
    },
     {
      "name": "Erlang",
          "department": "first-choice",
      "detail": ['71', '72', '73', '74'],
    },
  ];

完整实现代码

用StatefulWidget完成分组下拉展示及联动逻辑:

import 'package:flutter/material.dart';

class LinkedDropdownPage extends StatefulWidget {
  const LinkedDropdownPage({super.key});

  @override
  State<LinkedDropdownPage> createState() => _LinkedDropdownPageState();
}

class _LinkedDropdownPageState extends State<LinkedDropdownPage> {
  // 按部门分组后的分类数据
  Map<String, List<Map<String, dynamic>>> groupedCategories = {};
  // 当前选中的分类项
  Map<String, dynamic>? selectedCategory;
  // 当前选中的详情项
  String? selectedDetail;

  @override
  void initState() {
    super.initState();
    // 初始化分组数据
    _groupCategories();
  }

  // 将原始数据按department字段分组
  void _groupCategories() {
    for (final item in category123) {
      final dept = item['department'] as String;
      if (!groupedCategories.containsKey(dept)) {
        groupedCategories[dept] = [];
      }
      groupedCategories[dept]!.add(item);
    }
  }

  // 构建带分组标题的下拉选项
  List<DropdownMenuItem<Map<String, dynamic>>> _buildCategoryDropdownItems() {
    final items = <DropdownMenuItem<Map<String, dynamic>>>[];

    groupedCategories.forEach((dept, categoryList) {
      // 添加不可选的分组标题
      items.add(DropdownMenuItem(
        enabled: false,
        value: null,
        child: Padding(
          padding: const EdgeInsets.symmetric(horizontal: 8),
          child: Text(
            dept == 'first-choice' ? '第一选择' : '第二选择',
            style: const TextStyle(
              fontWeight: FontWeight.bold,
              color: Colors.grey,
            ),
          ),
        ),
      ));
      // 添加该分组下的所有语言选项
      for (final category in categoryList) {
        items.add(DropdownMenuItem(
          value: category,
          child: Text(category['name'] as String),
        ));
      }
    });

    return items;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('分组联动下拉')),
      body: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            // 第一个分组下拉列表
            const Text('选择编程语言'),
            DropdownButtonFormField<Map<String, dynamic>>(
              value: selectedCategory,
              hint: const Text('请选择'),
              items: _buildCategoryDropdownItems(),
              onChanged: (value) {
                setState(() {
                  selectedCategory = value;
                  selectedDetail = null; // 切换分类时重置详情选中状态
                });
              },
              decoration: const InputDecoration(
                border: OutlineInputBorder(),
                contentPadding: EdgeInsets.symmetric(horizontal: 12),
              ),
            ),
            const SizedBox(height: 20),
            // 第二个联动下拉列表
            const Text('选择详情'),
            if (selectedCategory != null)
              DropdownButtonFormField<String>(
                value: selectedDetail,
                hint: const Text('请选择'),
                items: (selectedCategory!['detail'] as List<String>)
                    .map((detail) => DropdownMenuItem(
                          value: detail,
                          child: Text(detail),
                        ))
                    .toList(),
                onChanged: (value) {
                  setState(() {
                    selectedDetail = value;
                  });
                },
                decoration: const InputDecoration(
                  border: OutlineInputBorder(),
                  contentPadding: EdgeInsets.symmetric(horizontal: 12),
                ),
              )
            else
              const Text('请先选择编程语言', style: TextStyle(color: Colors.grey)),
          ],
        ),
      ),
    );
  }
}

核心逻辑说明

  1. 分组处理:在initState中遍历原始数据,按department将数据归类到对应分组,为下拉列表的分组展示做准备
  2. 分组下拉构建:通过_buildCategoryDropdownItems生成下拉选项,分组标题设置为不可选,用加粗灰色文字区分,增强视觉层级
  3. 联动逻辑:选中第一个下拉的语言后,第二个下拉自动加载对应detail列表;切换语言时自动重置第二个下拉的选中值,避免数据不匹配

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 21:15:50