Flutter自定义DropdownButton选中后无法显示选中值问题求助
我正在尝试为DropdownButton创建自定义Widget,组件运行基本正常,触发onChanged()函数时控制台可打印出变更后的值,但执行onChanged()后下拉框无法显示选中的文本。
我的组件代码如下:
import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; class InputScreen2 extends StatefulWidget { final List<double> sizes; const InputScreen2({Key? key, required widget.sizes}) : super(key: key); @override State<InputScreen2> createState() => _InputScreen2State(); } class _InputScreen2State extends State<InputScreen2> { Future? future; double screenwd = 0, screenht = 0; List<String> listsex = ['Male', 'Female']; String? sex; @override void initState() { future = _future(); super.initState(); } Future<int> _future() async { SharedPreferences prefs = await SharedPreferences.getInstance(); screenwd = widget.sizes[0]; screenht = widget.sizes[1]; return 0; } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.orange, body: FutureBuilder( future: future, builder: (context, snapshot) { if (snapshot.hasError) { return Center( child: Text( 'Data Error...Please try again', style: Theme.of(context).textTheme.titleSmall, )); } else if (snapshot.connectionState == ConnectionState.waiting) { return Text( 'Waiting', style: Theme.of(context).textTheme.titleSmall, ); } else if (!snapshot.hasData) { return Text( 'No Data', style: Theme.of(context).textTheme.titleSmall, ); } else if (snapshot.hasData) { return SafeArea( child: Center( child: Container( padding: const EdgeInsets.all(20.0), decoration: BoxDecoration( border: Border.all(width: 2.0), color: Colors.blue), width: screenwd * .8, height: screenht * .75, child: SingleChildScrollView( child: Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.start, children: [ const Text( 'Personal Details', ), const SizedBox( width: 23, ), dropDownMenu('Sex', sex, listsex), ], ), ], ), ), ), ), ); } return const Text('No DATA'); })); } Widget dropDownMenu(String title, String? inputTxt, List<String> stringList) { return Container( margin: const EdgeInsets.only(top: 10.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( title, ), Container( width: 80, height: 35, decoration: BoxDecoration( border: Border.all(color: Colors.white, width: 1.0), borderRadius: const BorderRadius.all(Radius.circular(5.0))), child: DropdownButton<String>( value: inputTxt, dropdownColor: Colors.amber, items: stringList.map<DropdownMenuItem<String>>((String value) { return DropdownMenuItem<String>( value: value, child: Text( value, style: const TextStyle(color: Colors.white), )); }).toList(), onChanged: (String? value) { setState(() { inputTxt = value!; }); }), ), ], ), ); } }
问题原因
问题核心在于自定义的dropDownMenu函数中:
inputTxt是函数的局部参数,你在onChanged里调用setState修改的只是这个局部变量,并没有更新State类中定义的sex变量。- Flutter的UI渲染依赖State的状态值,由于
sex没有变化,DropdownButton的value始终保持初始值,导致选中后文本不更新。
解决方法
方法一:直接更新State中的变量
修改dropDownMenu函数的onChanged回调,直接操作State中的sex变量:
// 修改dropDownMenu内的onChanged部分 onChanged: (String? value) { setState(() { sex = value!; // 直接更新State中的sex变量 }); }
这样当选中选项时,sex变量被更新,setState触发UI重建,DropdownButton的value会同步为新选中的值,就能正确显示选中文本。
方法二:通过回调实现通用组件(推荐)
如果希望dropDownMenu作为通用组件,不直接依赖父组件的State变量,可以添加回调参数:
- 修改
dropDownMenu函数定义,增加回调参数:
Widget dropDownMenu( String title, String? inputTxt, List<String> stringList, Function(String?) onValueChanged, // 新增回调参数 ) { return Container( // ... 其他代码不变 child: DropdownButton<String>( value: inputTxt, // ... 其他代码不变 onChanged: onValueChanged, // 使用传入的回调 ), ); }
- 在调用
dropDownMenu时传入回调:
dropDownMenu('Sex', sex, listsex, (value) { setState(() { sex = value!; }); })
这种写法让自定义组件更灵活,可复用性更强。
内容的提问来源于stack exchange,提问作者gputhige
相关产品推荐
相关产品推荐

