Flutter Web:如何从Dialog中的DropDownList获取返回值
如何从Flutter自定义Dialog中获取DropdownList的选中值
问题场景
开发类移动端的Flutter Web应用,自定义Dialog包含三个DropDownList(ComboBox),外观和运行正常,但无法读取DropDownList的选中值,需要点击OK按钮后根据选中值跳转页面并填充内容。
解决方案
通过子组件回调传值+父组件统一管理状态+Dialog返回结果的方式实现,步骤如下:
1. 修改DropdownButtonExample组件,添加选中值回调
给子组件添加回调函数,用于将选中值传递给父Dialog组件:
import 'package:flutter/material.dart'; class DropdownButtonExample extends StatefulWidget { const DropdownButtonExample({ super.key, required this.listType, required this.onValueChanged, // 新增回调函数 }); final List<String> listType; final Function(String?) onValueChanged; // 传递选中值的回调 @override State<DropdownButtonExample> createState() => _DropdownButtonExampleState(); } class _DropdownButtonExampleState extends State<DropdownButtonExample> { String? dropdownValue; @override Widget build(BuildContext context) { return DropdownButton<String>( value: dropdownValue, icon: const Icon(Icons.arrow_downward), elevation: 10, style: const TextStyle(color: Colors.blue), underline: Container( height: 2, color: Colors.blue, ), onChanged: (String? value) { setState(() { dropdownValue = value; }); widget.onValueChanged(value); // 触发回调,传递选中值 }, items: widget.listType.map<DropdownMenuItem<String>>((String value) { return DropdownMenuItem<String>( value: value, child: Text(value), ); }).toList(), ); } }
2. 修改CustomDialogBox,管理选中状态并返回结果
在Dialog组件中维护三个DropDownList的选中值,点击OK时将结果返回给调用方:
class CustomDialogBox extends StatefulWidget { final String title, descriptions, text; const CustomDialogBox({ Key? key, required this.title, required this.descriptions, required this.text, }) : super(key: key); @override _CustomDialogBoxState createState() => _CustomDialogBoxState(); } class _CustomDialogBoxState extends State<CustomDialogBox> { String? selectedList1; // 存储第一个下拉框选中值 String? selectedList2; // 存储第二个下拉框选中值 String? selectedList3; // 存储第三个下拉框选中值 @override Widget build(BuildContext context) { return Dialog( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(15), ), elevation: 0, backgroundColor: Colors.transparent, child: contentBox(context), ); } contentBox(context) { return Stack( children: <Widget>[ Container( padding: const EdgeInsets.only(left: 50, top: 75, right: 50, bottom: 50), margin: const EdgeInsets.only(top: 40), decoration: BoxDecoration( shape: BoxShape.rectangle, color: Colors.white, borderRadius: BorderRadius.circular(15), ), child: Column( mainAxisSize: MainAxisSize.min, children: <Widget>[ const SizedBox(height: 80), Text( widget.title, style: const TextStyle(fontSize: 22, fontWeight: FontWeight.w600), ), const SizedBox(height: 15), Text( widget.descriptions, style: const TextStyle(fontSize: 14), textAlign: TextAlign.center, ), const SizedBox(height: 30), // 第一个下拉框,绑定回调 DropdownButtonExample( listType: list1, onValueChanged: (value) { setState(() => selectedList1 = value); }, ), const SizedBox(height: 30), // 第二个下拉框,绑定回调 DropdownButtonExample( listType: list2, onValueChanged: (value) { setState(() => selectedList2 = value); }, ), const SizedBox(height: 30), // 第三个下拉框,绑定回调 DropdownButtonExample( listType: list3, onValueChanged: (value) { setState(() => selectedList3 = value); }, ), Align( alignment: Alignment.bottomRight, child: MaterialButton( color: Colors.blue, onPressed: () { // 将三个选中值打包返回给调用方 Navigator.of(context).pop({ 'list1': selectedList1, 'list2': selectedList2, 'list3': selectedList3, }); }, child: Text( widget.text, style: const TextStyle(fontSize: 18, color: Colors.white), ), ), ), ], ), ), Positioned( left: 30, right: 30, top: 0, child: CircleAvatar( backgroundColor: Colors.blue, radius: 80, child: ClipRRect( borderRadius: BorderRadius.all(Radius.circular(75)), child: Image.network( "https://images.pexels.com/photos/627678/pexels-photo-627678.jpeg?auto=compress&cs=tinysrgb&w=1600", width: 120, height: 120, fit: BoxFit.fill, ), ), ), ), ], ); } } // 下拉框选项列表保持不变 const List<String> list1 = <String>[ 'One', 'Two', 'Three', 'Four', 'Five', 'Six', 'Seven', 'Eight', 'Nine', 'Ten', 'Eleven', 'Twelve' ]; const List<String> list2 = <String>[ 'Black', 'Red', 'Olive', 'DarkOliveGreen', 'MediumAquamarine', 'DarkSeaGreen', 'LightSeaGreen', 'DarkCyan', 'Teal' ]; const List<String> list3 = <String>['Slow', 'Medium', 'Fast'];
3. 在调用Dialog的页面接收结果并处理
通过await获取Dialog返回的选中值,后续执行页面跳转和内容填充逻辑:
// 示例:在main.dart中调用Dialog ElevatedButton( onPressed: () async { // 等待Dialog返回结果 var selectedValues = await showDialog( context: context, builder: (context) => CustomDialogBox( title: "选择参数", descriptions: "请选择三个选项", text: "确定", ), ); if (selectedValues != null) { // 解析选中值 String? val1 = selectedValues['list1']; String? val2 = selectedValues['list2']; String? val3 = selectedValues['list3']; // 根据选中值执行页面跳转和内容填充 Navigator.push( context, MaterialPageRoute( builder: (context) => TargetPage( value1: val1, value2: val2, value3: val3, ), ), ); } }, child: const Text("打开Dialog"), )
关键说明
- 子组件通过回调函数向父Dialog传递选中值,实现组件间通信
- Dialog统一管理所有下拉框的状态,点击OK时将结果通过
Navigator.pop()返回 - 调用方通过
await接收结果,完成后续业务逻辑
内容的提问来源于stack exchange,提问作者PrertoQuebas
相关产品推荐
相关产品推荐

