Flutter如何实现DropdownButtonFormField输入框与下拉列表文本不同?
实现自定义国家代码选择器
需求1:下拉显示完整名称+代码,选中后仅显示代码
直接利用DropdownButtonFormField的itemBuilder和selectedItemBuilder两个回调,分别控制下拉选项和选中后的显示内容:
class Country { final String name; final String code; Country(this.name, this.code); } // 在Widget中使用 DropdownButtonFormField<Country>( value: selectedCountry, decoration: InputDecoration( border: OutlineInputBorder(), hintText: '选择国家', ), // 下拉列表显示完整内容 itemBuilder: (context) { return countries.map((country) { return DropdownMenuItem( value: country, child: Text('${country.name} (${country.code})'), ); }).toList(); }, // 选中后仅显示国家代码 selectedItemBuilder: (context) { return countries.map((country) { return Text(country.code); }).toList(); }, onChanged: (value) { setState(() { selectedCountry = value; }); }, )
关键点:selectedItemBuilder返回的Widget仅在选中状态下显示,和itemBuilder分离即可实现两种不同的显示逻辑。
需求2:隐藏选中值,仅保留下拉按钮,自定义显示组件
如果要完全隐藏默认选中文本,只留下拉箭头,同时自行控制显示内容,有两种实现方式:
方式一:通过样式隐藏文本
将DropdownButtonFormField的文字样式设为透明,外部添加自定义显示组件:
Row( children: [ // 自定义显示区域 Container( padding: EdgeInsets.symmetric(horizontal: 12, vertical: 16), child: Text(selectedCountry?.code ?? '请选择'), ), Expanded( child: DropdownButtonFormField<Country>( value: selectedCountry, decoration: InputDecoration( border: OutlineInputBorder(), hintText: '', ), // 隐藏选中文本 style: TextStyle(color: Colors.transparent), // 下拉列表正常显示 itemBuilder: (context) { return countries.map((country) { return DropdownMenuItem( value: country, child: Text('${country.name} (${country.code})'), ); }).toList(); }, // 选中后返回空文本保持隐藏 selectedItemBuilder: (context) { return countries.map((country) { return Text('', style: TextStyle(color: Colors.transparent)); }).toList(); }, onChanged: (value) { setState(() { selectedCountry = value; }); }, ), ), ], )
方式二:用DropdownButton配合FormField实现完全自定义
这种方式无需hack手段,直接掌控整体布局:
FormField<Country>( builder: (state) { return Row( children: [ // 自定义显示区域 Container( padding: EdgeInsets.symmetric(horizontal: 12, vertical: 8), decoration: BoxDecoration( border: Border.all(color: Colors.grey), borderRadius: BorderRadius.only( topLeft: Radius.circular(4), bottomLeft: Radius.circular(4), ), ), child: Text(selectedCountry?.code ?? '请选择'), ), // 仅显示下拉按钮 Container( decoration: BoxDecoration( border: Border.all(color: Colors.grey), borderRadius: BorderRadius.only( topRight: Radius.circular(4), bottomRight: Radius.circular(4), ), ), child: DropdownButton<Country>( underline: SizedBox(), // 去掉默认下划线 value: selectedCountry, items: countries.map((country) { return DropdownMenuItem( value: country, child: Text('${country.name} (${country.code})'), ); }).toList(), onChanged: (value) { setState(() { selectedCountry = value; }); state.didChange(value); // 通知FormField状态变更 }, ), ), ], ); }, )
优势:完全自定义布局样式,避免透明文本这类临时方案,更贴合预期效果。
内容的提问来源于stack exchange,提问作者sodium
相关产品推荐
相关产品推荐

