You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中使用正则表达式验证喀麦隆手机号及识别运营商

喀麦隆手机号验证与运营商识别(Flutter实现)

原正则问题分析

你写的正则(^6+(?:\+?8|7|5[1-4])+[0-9]{9}$)存在几个关键问题:

  • 6+会匹配多个连续的6,不符合“以单个6开头”的规则
  • 分组后的+会重复匹配运营商前缀,导致格式混乱;且\+?完全多余,因为通用规则已经排除了特殊字符
  • 长度计算错误:喀麦隆手机号总长9位,原正则里[0-9]{9}会让总长度远超要求

修正后的正则表达式

先定义通用验证规则,再分别匹配MTN和Orange:

通用验证(确保符合喀麦隆手机号基础格式)

// 9位数字,以6开头,无其他字符
RegExp generalCameroonPhone = RegExp(r'^6\d{8}$');

MTN CM 匹配规则

// 第二位为7/8,或第二位为5且第三位是0-4,后续6位任意数字
RegExp mtnCMRegex = RegExp(r'^6(7|8|5[0-4])\d{6}$');

Orange CM 匹配规则

// 第二位为9,或第二位为5且第三位是5-9,后续6位任意数字
RegExp orangeCMRegex = RegExp(r'^6(9|5[5-9])\d{6}$');

完整实现步骤

1. 状态管理与运营商识别

用枚举标记当前识别的运营商,监听输入变化实时判断:

enum CameroonCarrier { none, mtn, orange }

class PhoneVerificationPage extends StatefulWidget {
  const PhoneVerificationPage({super.key});

  @override
  State<PhoneVerificationPage> createState() => _PhoneVerificationPageState();
}

class _PhoneVerificationPageState extends State<PhoneVerificationPage> {
  final TextEditingController _phoneController = TextEditingController();
  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
  CameroonCarrier _currentCarrier = CameroonCarrier.none;

  // 实时检查运营商
  void _checkCarrier(String input) {
    setState(() {
      if (!generalCameroonPhone.hasMatch(input)) {
        _currentCarrier = CameroonCarrier.none;
        return;
      }
      if (mtnCMRegex.hasMatch(input)) {
        _currentCarrier = CameroonCarrier.mtn;
      } else if (orangeCMRegex.hasMatch(input)) {
        _currentCarrier = CameroonCarrier.orange;
      } else {
        _currentCarrier = CameroonCarrier.none;
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('手机号验证')),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Form(
          key: _formKey,
          child: Column(
            children: [
              TextFormField(
                controller: _phoneController,
                keyboardType: TextInputType.phone,
                onChanged: _checkCarrier,
                decoration: InputDecoration(
                  labelText: '喀麦隆手机号',
                  hintText: '例如:688684749',
                  // 根据运营商显示Logo
                  suffixIcon: _currentCarrier == CameroonCarrier.mtn
                      ? Image.asset('assets/mtn_logo.png', width: 32, height: 32)
                      : _currentCarrier == CameroonCarrier.orange
                          ? Image.asset('assets/orange_logo.png', width: 32, height: 32)
                          : null,
                ),
                validator: (value) {
                  if (value == null || value.isEmpty) {
                    return '请输入手机号';
                  }
                  if (!generalCameroonPhone.hasMatch(value)) {
                    return '请输入有效的9位喀麦隆手机号(以6开头)';
                  }
                  if (_currentCarrier == CameroonCarrier.none) {
                    return '无法识别运营商,请检查号码';
                  }
                  return null;
                },
              ),
              const SizedBox(height: 20),
              ElevatedButton(
                onPressed: () {
                  // 验证通过才执行提交
                  if (_formKey.currentState?.validate() == true) {
                    // 这里写你的提交逻辑
                    ScaffoldMessenger.of(context).showSnackBar(
                      SnackBar(content: Text('提交号码:${_phoneController.text}')),
                    );
                  }
                },
                child: const Text('提交'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

2. 注意事项

  • 替换代码中的assets/mtn_logo.png和assets/orange_logo.png为你实际的Logo资源路径,并在pubspec.yaml中配置资源
  • 若需要处理带国家码+237的情况,可以在验证前先移除国家码,再用上述正则判断:
    String cleanedPhone = value.replaceAll(RegExp(r'^\+237'), '');
    

内容的提问来源于stack exchange,提问作者ASA Serge

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 08:05:15