Flutter:DropdownButtonFormField2屏幕旋转选中项重置及初始值设置问题
问题1:屏幕旋转后选中的财年被重置为初始值
原因
当前代码里selFinancialValue是StatelessWidget的成员变量,屏幕旋转时Widget会重建,成员变量会被重新初始化;同时每次进入FinancialYearList状态分支时,都会遍历列表设置当前财年为选中值,覆盖用户之前的选择。
解决步骤
将选中状态移至Bloc中存储:让Bloc的状态维护选中的财年值,确保状态在Widget重建(如屏幕旋转)时不会丢失。
- 修改Bloc的状态类,比如在
FinancialYearList中添加selectedValue字段,或利用已有的UpdateDropDown状态保存选中值。 - 仅在首次加载且无选中值时,才设置当前财年为默认值,否则保留用户已选的值。
- 修改Bloc的状态类,比如在
从Bloc状态中读取选中值:在
BlocBuilder中直接从状态获取选中值,不再依赖Widget的成员变量。
代码修改示例
调整Bloc状态处理逻辑
@override Widget build(BuildContext context) { context.read<MyAccountBloc>().add(FetchFinancialYearList(selectedCompany.id!)); return BlocBuilder<MyAccountBloc, MyAccountState>( builder: (context, state) { dynamic currentSelectedValue; List<dynamic>? currentFinancialYearList; if(state is FinancialYearList) { currentFinancialYearList = state.list; // 仅无选中值时,才设置当前财年为默认(可选逻辑) if(state.selectedValue == null && currentFinancialYearList != null) { for(dynamic itemFY in currentFinancialYearList) { if(DateTime.now().isBetween(yMdFormat.parse(itemFY['startDate']), yMdFormat.parse(itemFY['endDate']))) { currentSelectedValue = itemFY; break; } } } else { currentSelectedValue = state.selectedValue; } } else if(state is UpdateDropDown) { currentSelectedValue = state.selValue; // 从Bloc状态同步获取财年列表 currentFinancialYearList = context.read<MyAccountBloc>().state is FinancialYearList ? (context.read<MyAccountBloc>().state as FinancialYearList).list : null; } else { currentFinancialYearList = null; currentSelectedValue = null; } return MaterialApp( home: Scaffold( body: SafeArea( child: Stack( children: [ Container( child: Column( children: [ SizedBox(height: 3,), currentFinancialYearList == null ? SizedBox() : setFinancialPeriodDropDown(context, currentSelectedValue, currentFinancialYearList), SizedBox(height: 3,), // 原有Tab相关代码... ], ), ), // 原有底部按钮代码... ], ) ), ), ); } ); }
修改下拉菜单方法,接收外部传入的选中值和列表
Widget setFinancialPeriodDropDown(BuildContext context, dynamic selectedValue, List<dynamic> financialYearList) { return SizedBox( height: 45, child: DropdownButtonFormField2<dynamic>( isExpanded: true, hint: const Text('Select Financial Year',style: TextStyle(fontSize: 14),), value: selectedValue, items: financialYearList.map((item) => DropdownMenuItem<dynamic>( value: item, child: Text('${dMyFormat.format(yMdFormat.parse(item['startDate']))} :: ${dMyFormat.format(yMdFormat.parse(item['endDate']))}', style: const TextStyle(fontSize: 14,), ),)).toList(), validator: (value) { if (value == null) { return 'Please select Financial Year.'; } }, onChanged: (value) { context.read<MyAccountBloc>().add(UpdateDropDownEvent(selValue: value)); }, onSaved: (value) {}, ), ); }
问题2:页面打开时初始值设为“Select Financial Year”提示文本
解决方法
初始时将选中值设为null,DropdownButtonFormField2会自动显示hint属性中的文本。
具体调整
在FinancialYearList状态处理分支中,移除自动设置当前财年的逻辑,直接将选中值设为null:
if(state is FinancialYearList) { currentFinancialYearList = state.list; // 初始选中值设为null,显示hint文本 currentSelectedValue = state.selectedValue ?? null; }
这样页面打开时,下拉菜单会展示“Select Financial Year”,直到用户手动选择财年。
内容的提问来源于stack exchange,提问作者KJEjava48
相关产品推荐
相关产品推荐

