如何为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使用的掩码。具体实现步骤如下:
- 给
TextEditingController添加监听,实时提取输入的纯数字内容并计算长度 - 根据纯数字长度判断使用CPF还是CNPJ掩码
- 切换掩码时重新格式化现有文本,并触发组件更新
完整代码示例
// 定义全局掩码 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
相关产品推荐
相关产品推荐

