Flutter DropdownButtonFormField复用异常:两个实例选中状态同步
问题原因
你的两个下拉框组件共用了同一个GeneralController实例的selectedState状态变量,因此选中其中一个时,另一个会同步更新状态值。
解决方案
方案1:将组件改为受控组件(推荐,组件更通用)
修改MyStatesDropdown1,让它接收外部传入的状态变量和更新回调,实现每个实例独立绑定不同状态:
import 'package:flutter/material.dart'; import 'package:get/get.dart'; class MyStatesDropdown1 extends StatelessWidget { final RxString selectedState; final Function(String?) onChanged; MyStatesDropdown1({ super.key, required this.selectedState, required this.onChanged, }); final istates = [ {'scode': '35', 'sname': 'Andaman & Nicobar Islands'}, {'scode': '37', 'sname': 'Andhra Pradesh'}, {'scode': '12', 'sname': 'Arunachal Pradesh'}, {'scode': '18', 'sname': 'Assam'}, {'scode': '10', 'sname': 'Bihar'}, {'scode': '04', 'sname': 'Chandigarh'}, {'scode': '22', 'sname': 'Chattisgarh'}, {'scode': '26', 'sname': 'Dadra & Nagar Haveli & Daman & Diu'}, {'scode': '07', 'sname': 'Delhi'}, {'scode': '30', 'sname': 'Goa'}, {'scode': '24', 'sname': 'Gujarat'}, {'scode': '06', 'sname': 'Haryana'}, {'scode': '02', 'sname': 'Himachal Pradesh'}, {'scode': '01', 'sname': 'Jammu & Kashmir'}, {'scode': '20', 'sname': 'Jharkhand'}, {'scode': '29', 'sname': 'Karnataka'}, {'scode': '32', 'sname': 'Kerala'}, {'scode': '38', 'sname': 'Ladakh'}, {'scode': '31', 'sname': 'Lakshwadeep'}, {'scode': '23', 'sname': 'Madhya Pradesh'}, {'scode': '27', 'sname': 'Maharashtra'}, {'scode': '14', 'sname': 'Manipur'}, {'scode': '17', 'sname': 'Meghalaya'}, {'scode': '15', 'sname': 'Mizoram'}, {'scode': '13', 'sname': 'Nagaland'}, {'scode': '21', 'sname': 'Odisha'}, {'scode': '34', 'sname': 'Puducherry'}, {'scode': '03', 'sname': 'Punjab'}, {'scode': '08', 'sname': 'Rajasthan'}, {'scode': '11', 'sname': 'Sikkim'}, {'scode': '33', 'sname': 'Tamil Nadu'}, {'scode': '36', 'sname': 'Telangana'}, {'scode': '16', 'sname': 'Tripura'}, {'scode': '09', 'sname': 'Uttar Pradesh'}, {'scode': '15', 'sname': 'Uttrakhand'}, {'scode': '19', 'sname': 'West Bengal'} ]; @override Widget build(BuildContext context) { return Obx(() => Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Center( child: DropdownButtonFormField( decoration: InputDecoration( isDense: true, border: OutlineInputBorder( borderRadius: BorderRadius.circular(5.0), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(5.0), ), hintText: 'Select State', hintStyle: TextStyle(color: Colors.grey.shade800), ), value: selectedState.value == '' ? null : selectedState.value, onChanged: onChanged, items: istates.map((Map item) { return DropdownMenuItem<String>( value: item['scode'], child: Text(item['sname']), ); }).toList(), icon: const Icon(Icons.arrow_drop_down), iconSize: 42, ), ), ], )); } }
父页面使用方式
在包含标签页的页面中,定义两个独立的状态变量分别绑定到两个下拉框:
// 父页面中定义状态 final RxString billingSelectedState = ''.obs; final RxString shippingSelectedState = ''.obs; // 标签页内调用组件 TabBarView( children: [ // 账单地址标签页 MyStatesDropdown1( selectedState: billingSelectedState, onChanged: (newVal) { billingSelectedState.value = newVal ?? ''; // 如需同步到全局控制器,可在此调用: // _generalController.updateBillingState(newVal ?? ''); }, ), // 收货地址标签页 MyStatesDropdown1( selectedState: shippingSelectedState, onChanged: (newVal) { shippingSelectedState.value = newVal ?? ''; // _generalController.updateShippingState(newVal ?? ''); }, ), ], );
方案2:修改全局控制器,拆分独立状态
如果希望状态仍由GeneralController统一管理,可在控制器中添加两个独立的状态变量:
修改GeneralController
class GeneralController extends GetxController { // 拆分账单和收货地址的状态 final RxString billingSelectedState = ''.obs; final RxString shippingSelectedState = ''.obs; void updateBillingState(String state) { billingSelectedState.value = state; } void updateShippingState(String state) { shippingSelectedState.value = state; } }
修改下拉框组件
添加参数标记当前组件绑定的是账单还是收货地址:
class MyStatesDropdown1 extends StatelessWidget { final bool isBilling; final GeneralController _generalController = Get.find(); MyStatesDropdown1({ super.key, required this.isBilling, }); // 状态列表省略,同方案1... @override Widget build(BuildContext context) { final selectedState = isBilling ? _generalController.billingSelectedState : _generalController.shippingSelectedState; final updateMethod = isBilling ? _generalController.updateBillingState : _generalController.updateShippingState; return Obx(() => Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Center( child: DropdownButtonFormField( decoration: InputDecoration( isDense: true, border: OutlineInputBorder( borderRadius: BorderRadius.circular(5.0), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(5.0), ), hintText: 'Select State', hintStyle: TextStyle(color: Colors.grey.shade800), ), value: selectedState.value == '' ? null : selectedState.value, onChanged: (newVal) { if (newVal != null) { updateMethod(newVal); } }, items: istates.map((Map item) { return DropdownMenuItem<String>( value: item['scode'], child: Text(item['sname']), ); }).toList(), icon: const Icon(Icons.arrow_drop_down), iconSize: 42, ), ), ], )); } }
父页面使用方式
// 账单地址标签页 MyStatesDropdown1(isBilling: true), // 收货地址标签页 MyStatesDropdown1(isBilling: false),
内容的提问来源于stack exchange,提问作者gomesh munda
相关产品推荐
相关产品推荐

