如何为手机号输入框添加DropdownMenu下拉菜单
根据你的需求,这里提供两种常见的实现方式,适配Flutter的DropdownMenu组件或DropdownButtonFormField组件:
方式一:集成DropdownMenu到输入框右侧
这种方式是在现有TextField的右侧添加触发按钮,点击展开下拉菜单选择选项(比如国家码):
class PhoneInputWithDropdown extends StatefulWidget { const PhoneInputWithDropdown({super.key}); @override State<PhoneInputWithDropdown> createState() => _PhoneInputWithDropdownState(); } class _PhoneInputWithDropdownState extends State<PhoneInputWithDropdown> { final TextEditingController _phoneController = TextEditingController(); String? _selectedCode; final List<String> _codeOptions = ['+86', '+1', '+44', '+61']; bool _showMenu = false; @override Widget build(BuildContext context) { return SizedBox( width: 400, height: 60, child: Stack( alignment: Alignment.centerRight, children: [ TextField( controller: _phoneController, style: body1(color: ColorName.neutralTextPrimary), decoration: InputDecoration( enabledBorder: OutlineInputBorder( borderSide: const BorderSide(color: ColorName.neutralTextSecondary), borderRadius: BorderRadius.circular(10), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(10), borderSide: const BorderSide(color: ColorName.neutralTextSecondary), ), hintText: 'Phone Number', hintStyle: body1(color: ColorName.neutralTextSecondary), prefixText: _selectedCode ?? '+86 ', contentPadding: const EdgeInsets.symmetric(horizontal: 16), ), ), // 触发下拉菜单的按钮 IconButton( icon: Icon( _showMenu ? Icons.arrow_drop_up : Icons.arrow_drop_down, color: ColorName.neutralTextSecondary, ), onPressed: () => setState(() => _showMenu = !_showMenu), ), // 下拉菜单 if (_showMenu) Positioned( top: 60, left: 0, right: 0, child: Material( borderRadius: BorderRadius.circular(10), elevation: 4, child: DropdownMenu<String>( initialSelection: _selectedCode, dropdownMenuEntries: _codeOptions .map((code) => DropdownMenuEntry(value: code, label: code)) .toList(), onSelected: (value) { setState(() { _selectedCode = value; _showMenu = false; }); }, ), ), ), ], ), ); } }
关键说明:
- 用
StatefulWidget维护选中的选项和菜单显示状态 Stack布局让下拉菜单定位在输入框下方- 选中选项后自动关闭菜单,并更新输入框的前缀文本
方式二:拆分下拉框与输入框(更适合手机号场景)
如果是选择国家码+输入手机号的场景,用Row拆分两个组件,视觉上保持统一:
class PhoneCodeInput extends StatefulWidget { const PhoneCodeInput({super.key}); @override State<PhoneCodeInput> createState() => _PhoneCodeInputState(); } class _PhoneCodeInputState extends State<PhoneCodeInput> { final TextEditingController _phoneController = TextEditingController(); String? _selectedCode; final List<String> _codeOptions = ['+86', '+1', '+44', '+61']; @override Widget build(BuildContext context) { return SizedBox( width: 400, height: 60, child: Row( children: [ // 国家码下拉框 SizedBox( width: 100, child: DropdownButtonFormField<String>( value: _selectedCode, decoration: InputDecoration( enabledBorder: OutlineInputBorder( borderSide: const BorderSide(color: ColorName.neutralTextSecondary), borderRadius: const BorderRadius.only( topLeft: Radius.circular(10), bottomLeft: Radius.circular(10), ), ), focusedBorder: OutlineInputBorder( borderRadius: const BorderRadius.only( topLeft: Radius.circular(10), bottomLeft: Radius.circular(10), ), borderSide: const BorderSide(color: ColorName.neutralTextSecondary), ), hintText: 'Code', hintStyle: body1(color: ColorName.neutralTextSecondary), contentPadding: const EdgeInsets.symmetric(horizontal: 8), ), items: _codeOptions .map((code) => DropdownMenuItem(value: code, child: Text(code))) .toList(), onChanged: (value) => setState(() => _selectedCode = value), ), ), // 手机号输入框 Expanded( child: TextField( controller: _phoneController, style: body1(color: ColorName.neutralTextPrimary), decoration: InputDecoration( enabledBorder: OutlineInputBorder( borderSide: const BorderSide(color: ColorName.neutralTextSecondary), borderRadius: const BorderRadius.only( topRight: Radius.circular(10), bottomRight: Radius.circular(10), ), ), focusedBorder: OutlineInputBorder( borderRadius: const BorderRadius.only( topRight: Radius.circular(10), bottomRight: Radius.circular(10), ), borderSide: const BorderSide(color: ColorName.neutralTextSecondary), ), hintText: 'Phone Number', hintStyle: body1(color: ColorName.neutralTextSecondary), contentPadding: const EdgeInsets.symmetric(horizontal: 16), ), ), ), ], ), ); } }
关键说明:
- 拆分后的组件分别设置左右圆角,视觉上形成一个完整的输入框
DropdownButtonFormField自带表单集成,无需手动管理菜单状态- 更符合手机号输入的用户习惯
内容的提问来源于stack exchange,提问作者Bilbo Baggins
相关产品推荐
相关产品推荐

