Flutter印度手机号验证失效问题排查与修复求助
印度手机号验证界面校验问题修复
问题描述
开发印度手机号验证界面时,当前代码无法完成有效校验,需求为:验证通过则调用API,未通过则高亮TextFormField并显示错误提示。
原代码
Form( key: _formKeymobile, child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ Text( S.of(context).verify, style: TextStyle( fontSize: 30.0.sp, fontFamily: 'DancingScript', color: Colors.purple), ), SizedBox( height: 20, ), TextFormField( style: TextStyle(color: Colors.blue, fontSize: 20.0.sp), controller: _mobilenumber, validator: (value) { const pattern = r'(^(?:(?:\+|0{0,2})91(\s*[\ -]\s*)?|[0]?)?[6789]\d{9}|(\d[ -]?){10}\d$)'; final regExp = RegExp(pattern); if (value!.isEmpty) { return S.of(context).EnterSomeText; } else if (value.length != 10) { } else if (!regExp.hasMatch(value)) { return S.of(context).Mobilenumbermust10digits; return S.of(context).MobileNumbermustbedigits; } }, maxLength: 11, keyboardType: TextInputType.phone, decoration: InputDecoration( hintText: S.of(context).mobile, border: OutlineInputBorder()), ), SizedBox( height: 8.0, ), Row( children: [ Checkbox( checkColor: Colors.white, value: isChecked, onChanged: (bool? value) { setState(() { isChecked = value!; }); // print(isChecked); }, ), SizedBox( width: MediaQuery.of(context).size.width * 0.60, child: Column( children: [ Text(S.of(context).tcone), InkWell( onTap: () { openWebsite( context); }, child: Text( S.of(context).tctwo, style: TextStyle(color: Colors.blue), )), Text("and"), InkWell( onTap: () { openWebsite( context); }, child: Text( S.of(context).tcthree, style: TextStyle(color: Colors.blue), )), ], ), ) ], ), ElevatedButton( onPressed: () async { if (isChecked == true) { if (_formKeymobile.currentState!.validate() && isChecked == true) { String? deviceId = await _getId(); if (deviceId != null) { print("api called"); } else { EasyLoading.showError("Unable to get device id"); } } } else { EasyLoading.showError("Please click the box"); } }, style: ButtonStyle( backgroundColor: MaterialStateProperty.all(Colors.purple)), child: Text(S.of(context).otp), ), SizedBox( height: 8.0, ), ElevatedButton( onPressed: () async { if (_formKeymobile.currentState!.validate() && isChecked == true) { print("form validated"); } }, style: ButtonStyle( backgroundColor: MaterialStateProperty.all(Colors.green)), child: Text("Already have OTP"), ), ], )
问题分析与修复方案
1. 校验逻辑漏洞
- 原
validator中,当手机号长度不符合要求时,无错误返回,导致该校验步骤完全失效; - 正则不匹配分支存在两个连续
return语句,第二个永远无法执行,属于明显逻辑错误。
2. 正则表达式优化
原正则过于冗余,印度手机号标准格式包含两种情况:
- 纯10位数字,以6/7/8/9开头;
- 带
+91前缀或0前缀的10位数字。
简化后的正则更精准易维护:r'^(?:\+91|0)?[6789]\d{9}$'
3. 输入长度调整
若允许用户输入带+91前缀的手机号,maxLength应设为13(+91+10位数字);若仅允许纯10位手机号,设为10即可。
修复后的核心代码
TextFormField( style: TextStyle(color: Colors.blue, fontSize: 20.0.sp), controller: _mobilenumber, validator: (value) { // 简化后的印度手机号校验正则 const pattern = r'^(?:\+91|0)?[6789]\d{9}$'; final regExp = RegExp(pattern); if (value!.isEmpty) { return S.of(context).EnterSomeText; } // 统一校验格式,不符合则返回错误提示 else if (!regExp.hasMatch(value)) { return S.of(context).Mobilenumbermust10digits; } // 校验通过必须返回null return null; }, // 允许带+91前缀,设置最大长度为13 maxLength: 13, keyboardType: TextInputType.phone, decoration: InputDecoration( hintText: S.of(context).mobile, border: OutlineInputBorder()), )
额外优化点
- 原按钮逻辑中重复判断
isChecked == true,可简化为一次判断; - 修复后,校验不通过时
Form会自动高亮TextFormField并显示错误提示,无需额外手动处理。
内容的提问来源于stack exchange,提问作者Navjot Aulakh
相关产品推荐
相关产品推荐

