Flutter TextFormField如何实现邮箱输入必含@和.的校验规则
Flutter TextFormField 邮箱格式校验实现方案
直接在现有代码基础上补充逻辑即可,不需要重构现有功能,核心是区分「格式错误」「邮箱已占用」两种错误状态,保证提示优先级和状态联动正确。
1. 新增格式校验判断方法
先写基础的格式判断函数,匹配要求的校验规则:输入必须同时包含@和.,同时排除明显的边界异常情况:
/// 校验邮箱格式是否符合要求 bool checkEmailFormatValid(String input) { // 核心规则:必须包含@和. if (!input.contains('@') || !input.contains('.')) { return false; } final int atPos = input.indexOf('@'); final int lastDotPos = input.lastIndexOf('.'); // 边界校验:@不能在开头、.不能在结尾、@必须在.前面 return atPos > 0 && lastDotPos < input.length - 1 && atPos < lastDotPos; }
2. 补充状态变量与联动逻辑
在组件状态类里新增一个格式错误的标识位,和已有的isEmailInvalid(邮箱已占用)、isEmailvalid(校验通过)状态联动:
// 新增状态:标记邮箱格式是否错误 bool isEmailFormatError = false;
3. 修改TextFormField对应逻辑
调整onChanged、decoration配置,补充validator属性适配Form表单校验场景,修改后的完整代码如下:
TextFormField( keyboardType: TextInputType.emailAddress, inputFormatters: [ FilteringTextInputFormatter.allow( RegExp("[a-z0-9@._-]")), ], // 适配Form表单的校验逻辑 validator: (val) { if (val == null || !checkEmailFormatValid(val)) { return "You should enter valid email address"; } if (isEmailInvalid) { return "Email is already taken"; } return null; }, onChanged: (text) { setState(() { // 每次输入先校验格式 isEmailFormatError = !checkEmailFormatValid(text); if (isEmailFormatError) { // 格式错误时重置占用状态,不触发查重请求 isEmailInvalid = false; } else { // 仅格式合法时才触发查重逻辑,减少无效接口调用 _onSearchChanged(text); } // 更新通过状态:格式合法 + 未被占用 isEmailvalid = !isEmailFormatError && !isEmailInvalid; }); }, controller: emailController, decoration: InputDecoration( // 错误提示优先级:格式错误 > 邮箱已占用 errorText: isEmailFormatError ? "You should enter valid email address" : (isEmailInvalid ? "Email is already taken" : null), hintText: 'Enter your email', // 仅双条件满足时显示绿色通过对勾 suffixIcon: isEmailvalid ? const Icon( Icons.check, color: Colors.green, ) : const Icon( Icons.check_circle, color: Colors.transparent) )),
逻辑说明
- 输入内容缺少
@或.时,会立即显示格式错误提示,不会触发邮箱查重请求 - 格式校验通过后才会走原有的邮箱占用校验逻辑,避免无效接口调用
- 只有格式正确、且邮箱未被占用两个条件同时满足时,才会显示绿色对勾的通过图标
- 如果你用
Form组件包裹输入框,调用表单校验方法时会自动触发validator逻辑,和手动控制的提示状态不冲突
内容的提问来源于stack exchange,提问作者Dimas Satrya
相关产品推荐
相关产品推荐

