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

如何为TextField实现自适应掩码:切换CPF/CNPJ输入格式

实现自适应CPF/CNPJ掩码的TextField功能

需求:开发一个用于更新用户信息的TextField,要求用户输入11位(CPF)或14位(CNPJ)数字,当输入超过11位时自动切换输入掩码。现有如下CPF和CNPJ掩码实现,需完成自适应切换功能:

现有掩码代码

var mascaraCpf = MaskTextInputFormatter(
  mask: '###.###.###-##',
  filter: {"#": RegExp(r'[0-9]')},
  type: MaskAutoCompletionType.lazy
);

var mascaraCnpj = MaskTextInputFormatter(
  mask: '##.###.###/####-##',
  filter: {"#": RegExp(r'[0-9]')},
  type: MaskAutoCompletionType.lazy
);

自适应切换实现方案

核心思路是监听输入文本的纯数字长度,动态切换TextField使用的掩码。具体实现步骤如下:

  1. 给TextEditingController添加监听,实时提取输入的纯数字内容并计算长度
  2. 根据纯数字长度判断使用CPF还是CNPJ掩码
  3. 切换掩码时重新格式化现有文本,并触发组件更新

完整代码示例

// 定义全局掩码
final mascaraCpf = MaskTextInputFormatter(
  mask: '###.###.###-##',
  filter: {"#": RegExp(r'[0-9]')},
  type: MaskAutoCompletionType.lazy
);

final mascaraCnpj = MaskTextInputFormatter(
  mask: '##.###.###/####-##',
  filter: {"#": RegExp(r'[0-9]')},
  type: MaskAutoCompletionType.lazy
);

// 控制器及状态变量
final cpfController = TextEditingController();
late MaskTextInputFormatter currentMask;

@override
void initState() {
  super.initState();
  currentMask = mascaraCpf;
  // 添加文本变化监听
  cpfController.addListener(() {
    // 提取纯数字内容,排除掩码符号
    final digitsOnly = cpfController.text.replaceAll(RegExp(r'[^0-9]'), '');
    
    // 切换为CNPJ掩码的条件
    if (digitsOnly.length > 11 && currentMask != mascaraCnpj) {
      currentMask = mascaraCnpj;
      // 重新格式化现有文本
      final formattedText = currentMask.formatEditUpdate(
        TextEditingValue(text: digitsOnly),
        TextEditingValue(text: digitsOnly)
      );
      cpfController.value = formattedText;
      setState(() {});
    } 
    // 切换回CPF掩码的条件
    else if (digitsOnly.length <= 11 && currentMask != mascaraCpf) {
      currentMask = mascaraCpf;
      final formattedText = currentMask.formatEditUpdate(
        TextEditingValue(text: digitsOnly),
        TextEditingValue(text: digitsOnly)
      );
      cpfController.value = formattedText;
      setState(() {});
    }
  });
}

@override
void dispose() {
  cpfController.dispose();
  super.dispose();
}

// 最终的TextField组件
TextField(
  keyboardType: TextInputType.number,
  inputFormatters: [
    currentMask,
    FilteringTextInputFormatter.digitsOnly
  ],
  controller: cpfController,
  decoration: InputDecoration(
    filled: true,
    fillColor: const Color(0xffFCF9F4),
    border: OutlineInputBorder(
      borderRadius: BorderRadius.circular(5)
    ),
    hintText: appModel.usuario!.cpf,
  ),
)

关键说明

  • 监听文本变化时,先提取纯数字内容,避免掩码中的符号干扰长度判断
  • 切换掩码后调用formatEditUpdate重新格式化文本,保证格式与当前掩码匹配
  • 通过setState触发TextField重新渲染,更新输入格式化器列表

内容的提问来源于stack exchange,提问作者Lucas Benevenute

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 23:06:11