Flutter桌面端setState无法更新屏幕下拉框选中值
问题根因
所有需要随组件生命周期保留的状态变量、表单Key、下拉选项列表都被写在了build方法内部。setState的本质是触发组件重新执行build方法重绘界面,每次重绘时这些写在build里的变量都会被重新初始化,_dropdownvalue会被直接重置为初始值"Global admin",导致选中操作的修改被覆盖,界面上看不到更新效果。
修复方案
- 将
_formKey、_dropdownvalue、_items三个变量从build方法内部移到_LoginViewState类的成员属性位置,保证变量不会在每次重绘时被重置。 - 修正下拉选项构造时的变量名冲突问题:原代码中
map方法的入参命名和外层列表_items重名,容易引发值引用混乱,建议将入参名改为不冲突的命名。
修复后完整代码
import 'package:demo_app_admin/Custom/custom_Font.dart'; import 'package:flutter/material.dart'; import '/Custom/Custom_Raised_Bottun.dart'; import '/Custom/Header.dart'; import '/Custom/inputField.dart'; class LoginView extends StatefulWidget { @override _LoginViewState createState() => _LoginViewState(); } class _LoginViewState extends State<LoginView> { // 所有持久化状态移到build方法外,作为State类成员 final GlobalKey<FormState> _formKey = GlobalKey<FormState>(); String _dropdownvalue = "Global admin"; final List<String> _items = <String>["Global admin", "Institution admin"]; @override Widget build(BuildContext context) { final isKeyboard = MediaQuery.of(context).viewInsets.bottom != 0; return Scaffold( body: Container( width: double.infinity, decoration: BoxDecoration( gradient: LinearGradient(begin: Alignment.topCenter, colors: [ Colors.teal[700]!, Colors.teal[200]!, Colors.teal[400]! ]), ), child: Column( children: <Widget>[ const SizedBox(height: 80), if (!isKeyboard) Header( padding: const EdgeInsets.all(20), crossAxisAlignment: CrossAxisAlignment.start, head: "Welcome", headTextStyle: const TextStyle(color: Colors.white, fontSize: 40), sizedBoxHeight: 10, subtitle: "Sign In to Your Admin Account", subtitleTextStyle: const TextStyle(color: Colors.white, fontSize: 18), ), Expanded( child: Container( decoration: const BoxDecoration( color: Colors.white, borderRadius: BorderRadius.only( topLeft: Radius.circular(60), topRight: Radius.circular(60), )), child: Padding( padding: const EdgeInsets.all(30), child: SingleChildScrollView( reverse: true, padding: EdgeInsets.all(32), child: Form( key: _formKey, child: Column( children: <Widget>[ const SizedBox(height: 40), Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(10)), child: Column( children: <Widget>[ InputField( labelText: 'Email', padding: EdgeInsets.all(10), borderSide: BorderSide(color: Colors.grey), hintText: "Enter your email", color: Colors.grey, inputBorder: InputBorder.none, obscureText: false, enableSuggestion: true, autoCorrect: true, onSaved: (value) {}, validator: (value) { if (value == null) { print("ERROR"); } }, ), InputField( labelText: 'Password', padding: EdgeInsets.all(10), borderSide: BorderSide(color: Colors.grey), hintText: "Enter your password", color: Colors.grey, inputBorder: InputBorder.none, obscureText: true, enableSuggestion: false, autoCorrect: false, onSaved: (value) {}, validator: (value) { if (value == null) { print("ERROR"); } }, ), ], ), ), const SizedBox(height: 40), DropdownButton<String>( value: _dropdownvalue, icon: Icon(Icons.keyboard_arrow_down), // 修正入参命名,避免和外层列表重名 items: _items.map((String item) { return DropdownMenuItem<String>( value: item, child: CustomFont(text: item), ); }).toList(), onChanged: (value) { setState(() => _dropdownvalue = value!); }), const SizedBox(height: 40), CustomRaisedButton( width: 200, height: 50.0, margin: const EdgeInsets.symmetric(horizontal: 50), color: Colors.teal.shade500, borderRadius: BorderRadius.circular(10), text: "LOGIN", textColor: Colors.white, fontSize: 17, fontWeight: FontWeight.bold, function: () {}), const SizedBox(height: 10), ], ), ), ), ), )) ], ), ), ); } }
内容的提问来源于stack exchange,提问作者Mohammad Al-Zoubi
相关产品推荐
相关产品推荐

