基于给定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)), ], ), ), ); } }
核心逻辑说明
- 分组处理:在
initState中遍历原始数据,按department将数据归类到对应分组,为下拉列表的分组展示做准备 - 分组下拉构建:通过
_buildCategoryDropdownItems生成下拉选项,分组标题设置为不可选,用加粗灰色文字区分,增强视觉层级 - 联动逻辑:选中第一个下拉的语言后,第二个下拉自动加载对应
detail列表;切换语言时自动重置第二个下拉的选中值,避免数据不匹配
内容的提问来源于stack exchange,提问作者Edward
相关产品推荐
相关产品推荐

