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

Flutter中如何实现输入时不消失的手机号输入框掩码?

Flutter 实现常驻不消失的手机号输入掩码

完全可以实现,不需要额外引入第三方插件,核心是自定义文本输入格式化器,强制输入内容始终匹配预设的掩码规则,让格式分隔符常驻、占位内容随用户输入逐步替换。

实现思路

  • 预设手机号掩码规则:国内手机号通用格式为 ### #### ####(# 为数字占位位,空格为固定格式分隔符,全程不消失)
  • 重写TextInputFormatter的formatEditUpdate方法,每次输入变化时自动补全固定分隔符、过滤非法输入、保证光标位置正确
  • 未输入的占位位通过文字样式设为灰色,已输入内容用常规文本颜色,视觉上达到占位符逐步替换的效果

完整可运行代码示例

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class PermanentPhoneMaskFormatter extends TextInputFormatter {
  static const mask = '### #### ####';
  static const separator = ' ';

  @override
  TextEditingValue formatEditUpdate(
      TextEditingValue oldValue, TextEditingValue newValue) {
    // 过滤非数字输入
    final inputDigits = newValue.text.replaceAll(RegExp(r'[^0-9]'), '');
    // 限制最大输入长度为11位手机号
    if (inputDigits.length > 11) return oldValue;

    final buffer = StringBuffer();
    int inputIndex = 0;

    // 逐位拼接掩码,固定分隔符自动补全
    for (int i = 0; i < mask.length; i++) {
      if (inputIndex >= inputDigits.length) break;
      if (mask[i] == separator) {
        buffer.write(separator);
      } else {
        buffer.write(inputDigits[inputIndex]);
        inputIndex++;
      }
    }

    final formattedText = buffer.toString();
    return TextEditingValue(
      text: formattedText,
      // 光标始终保持在输入内容末尾
      selection: TextSelection.collapsed(offset: formattedText.length),
    );
  }
}

// 组件调用示例
class PhoneInputPage extends StatelessWidget {
  const PhoneInputPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('手机号输入测试')),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Stack(
          alignment: Alignment.centerLeft,
          children: [
            // 底层常驻掩码占位,未输入位显示灰色
            Text(
              '___ ____ ____',
              style: TextStyle(
                fontSize: 16,
                color: Colors.grey[300],
                letterSpacing: 1.2,
              ),
            ),
            // 上层实际输入框
            TextField(
              keyboardType: TextInputType.phone,
              inputFormatters: [PermanentPhoneMaskFormatter()],
              style: const TextStyle(
                fontSize: 16,
                color: Colors.black,
                letterSpacing: 1.2,
              ),
              decoration: const InputDecoration(
                border: InputBorder.none,
                counterText: '',
                filled: false,
              ),
            ),
          ],
        ),
      ),
    );
  }
}

交互效果说明

  • 初始状态下显示灰色完整掩码占位
  • 用户输入数字时,数字从左到右依次替换对应位置的占位符,分隔空格始终保留,不会被输入/删除操作影响
  • 自动过滤非数字内容,输入到11位手机号后无法继续输入
  • 退格删除时只会删除已输入的数字,固定分隔符自动保留,不会出现格式错乱

如果需要调整掩码格式(比如改成带区号的格式、银行卡号格式),只需要修改PermanentPhoneMaskFormatter里的mask规则即可,逻辑通用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 08:48:17