Flutter中DropdownButton切换用户时更新TextFormField内容及实现用户信息分权限展示的问题
我看了你的代码,问题出在TextFormField的initialValue属性上——它只在组件第一次初始化的时候生效,之后哪怕你通过setState更新了_currentUser,这个值也不会自动同步到输入框里。咱们来一步步解决这个问题:
核心问题分析
initialValue是一次性的初始化参数,组件构建完成后,它不会响应后续的状态变化。要实现动态更新输入框内容,你需要使用TextEditingController来控制TextFormField的文本。
具体解决方案
为可编辑字段创建对应的TextEditingController
比如你要编辑的perfil字段,单独声明一个控制器:final _perfilController = TextEditingController();在切换用户时更新控制器的文本
在DropdownButton的onChanged回调里,除了更新_currentUser,还要同步更新控制器的内容:onChanged:(Utilizador? value) { setState(() { _currentUser = value; if (value != null) { _perfilController.text = value.perfil.toString(); } }); }将控制器绑定到TextFormField
把TextFormField的controller属性设置为你创建的控制器,去掉initialValue:TextFormField( controller: _perfilController, decoration: InputDecoration( label: Text("Perfil"), floatingLabelBehavior:FloatingLabelBehavior.always, border: OutlineInputBorder(), ), )记得在组件销毁时释放控制器
重写dispose方法,避免内存泄漏:@override void dispose() { _perfilController.dispose(); super.dispose(); }
修改后的完整代码
class UtilizadorPage extends StatefulWidget { @override _UtilizadorPageState createState() => new _UtilizadorPageState(); } class _UtilizadorPageState extends State<UtilizadorPage> { Utilizador user = Utilizador(); BDLocal db = BDLocal.instance; Utilizador? _currentUser; final _perfilController = TextEditingController(); // 添加控制器 @override void initState(){ super.initState(); } @override void dispose() { _perfilController.dispose(); // 释放控制器 super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text( "Utilizadores", ), ), body: Column( children: [ Row( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ FutureBuilder<List<Utilizador>>( future: user.getUtilizadores(), builder: (BuildContext context, AsyncSnapshot<List<Utilizador>> snapshot){ if (snapshot.hasError) return Text('加载用户列表出错'); // 增加错误处理 if (!snapshot.hasData) return CircularProgressIndicator(); return DropdownButton<Utilizador>( alignment: Alignment.center, items: snapshot.data?.map((util) => DropdownMenuItem<Utilizador>( child: Text(util.nome), value: util, )).toList(), onChanged:(Utilizador? value) { setState(() { _currentUser = value; // 更新控制器文本 if (value != null) { _perfilController.text = value.perfil.toString(); } }); }, isExpanded: false, value: _currentUser, // 恢复这个属性,保持选中状态 hint: Text('Select User'), ); }), ] ), SizedBox(height: 20.0), Row( children: [ _currentUser != null ? Expanded( child: Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ Expanded( flex: 1, child: Container( child: InputDecorator( decoration: InputDecoration( labelText: "Nome", floatingLabelBehavior:FloatingLabelBehavior.always, border: OutlineInputBorder(), ), child: Text(_currentUser!.nome) ), ), ), SizedBox(width: 10.0), Expanded( flex: 1, child: Container( child: InputDecorator( decoration: InputDecoration( labelText: "ID na BDNuvem", floatingLabelBehavior:FloatingLabelBehavior.always, border: OutlineInputBorder(), ), child: Text(_currentUser!.id_BDNuvem.toString()) ), ), ), ]), SizedBox(height: 20.0), Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ Expanded( flex: 1, child: TextFormField( controller: _perfilController, // 使用控制器 decoration: InputDecoration( label: Text("Perfil"), floatingLabelBehavior:FloatingLabelBehavior.always, border: OutlineInputBorder(), ), ), ), SizedBox(width: 10.0), Expanded( flex: 1, child: Container( child: InputDecorator( decoration: InputDecoration( labelText: "Numero de Colaborador", floatingLabelBehavior:FloatingLabelBehavior.always, border: OutlineInputBorder(), ), child: Text(_currentUser!.numero.toString()) ), ), ), ], ), SizedBox(height: 20.0), Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ Expanded( flex: 1, child: Container( child: InputDecorator( decoration: InputDecoration( labelText: "Nome do Funcionario", floatingLabelBehavior:FloatingLabelBehavior.always, border: OutlineInputBorder(), ), child: Text(_currentUser!.nomeFuncionario) ), ), ), ], ), SizedBox(height: 20.0), Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ Expanded( flex: 1, child: Container( child: InputDecorator( decoration: InputDecoration( labelText: "Email", floatingLabelBehavior:FloatingLabelBehavior.always, border: OutlineInputBorder(), ), child: Text(_currentUser!.email) ), ), ), ], ), SizedBox(height: 20.0), Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ Expanded( flex: 1, child: Container( child: InputDecorator( decoration: InputDecoration( labelText: "Senha", floatingLabelBehavior:FloatingLabelBehavior.always, border: OutlineInputBorder(), ), child: Text(_currentUser!.senha) ), ), ), ], ), SizedBox(height: 20.0), Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ Expanded( flex: 1, child: Container( child: InputDecorator( decoration: InputDecoration( labelText: "Ultima Atualizacao", floatingLabelBehavior:FloatingLabelBehavior.always, border: OutlineInputBorder(), ), child: Text(_currentUser!.ultimaAtualizacao) ), ), ), SizedBox(width: 10.0), Expanded( flex: 1, child: Container( child: InputDecorator( decoration: InputDecoration( labelText: "Atualizado Por", floatingLabelBehavior:FloatingLabelBehavior.always, border: OutlineInputBorder(), ), child: Text(_currentUser!.atualizadoPor) ), ), ), ], ), ], ), ) : Text("No User selected"), ] ) ], ), ); } }
额外提示
- 我帮你恢复了DropdownButton的
value: _currentUser属性,这样切换后下拉框会保持选中的用户,不会每次重建都回到hint状态。 - 增加了FutureBuilder的错误处理,避免加载失败时只显示加载指示器。
- 如果以后有更多可编辑字段,只需要为每个字段创建对应的TextEditingController,然后在onChanged里同步更新即可。
内容的提问来源于stack exchange,提问作者Martim Fernandes
相关产品推荐
相关产品推荐

