Flutter 手机号 输入框 格式化输入

最近在做自家产品的时候,需要用到手机号登陆,而产品要求的格式是 XXX XXXX XXXX,即中间需要有空格。Flutter 默认的输入框无法满足,需要自己写一个 InputFormatter。

效果图

效果图

代码解析

源码如下:

import 'package:flutter/services.dart';

TextInputFormatter phoneInputFormatter() {
  return TextInputFormatter.withFunction((oldValue, newValue) {
    String text = newValue.text;
    //获取光标左边的文本
    final positionStr = (text.substring(0, newValue.selection.baseOffset)).replaceAll(RegExp(r"\s+\b|\b\s"), "");
    //计算格式化后的光标位置
    int length = positionStr.length;
    var position = 0;
    if (length <= 3) {
      position = length;
    } else if (length <= 7) {
      // 因为前面的字符串里面加了一个空格
      position = length + 1; 
    } else if (length <= 11) {
      // 因为前面的字符串里面加了两个空格
      position = length + 2; 
    } else {
      // 号码本身为 11 位数字,因多了两个空格,故为 13
      position = 13;
    }

    //这里格式化整个输入文本
    text = text.replaceAll(RegExp(r"\s+\b|\b\s"), "");
    var string = "";
    for (int i = 0; i < text.length; i++) {
      // 这里第 4 位,与第 8 位,我们用空格填充
      if (i == 3 || i == 7) {
        if (text[i] != " ") {
          string = string + " ";
        }
      }
      string += text[i];
    }
    
    return TextEditingValue(
      text: string,
      selection: TextSelection.fromPosition(TextPosition(offset: position, affinity: TextAffinity.upstream)),
    );
  });
}
复制代码

里面注释写得比较详细,如发现我有没说明白的地方,可以评论区留言。

使用

源码如下:


class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Container(
              padding: const EdgeInsets.symmetric(horizontal: 40),
              child: TextField(
                keyboardType: TextInputType.phone,
                style: const TextStyle(fontSize: 20),
                inputFormatters: [
                  phoneInputFormatter(),
                  LengthLimitingTextInputFormatter(13),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}
复制代码

这里面还有一个有意思的地方就是 LengthLimitingTextInputFormatter,这个 InputFormatter 用于限制输入的长度(比如我们这里为 13)。

此时,有朋友可能就想到了,用 TextField 属性 MaxLength 不也可以限制长度吗?确实是的,只不过用 MaxLength 的时候,输入框右下方会出现 13/13 字样,而这是我们不需要的,因此用了这个限制长度的格式化器来帮我们处理。

对于右下方的 13/13 字样,如果我们不使用 LengthLimitingTextInputFormatter,我们也可以通过实现 TextField 中的 buildCounter 属性,来进行适当的消除。有兴趣的朋友可以去尝试尝试。

相信通过这个简单的自定义格式化器,我们也能够实现其他的一些格式化器,这篇文章就讲到这里

若朋友不嫌弃,给个关注呗,让我们共同探索互联网新技术

猜你喜欢

转载自juejin.im/post/7088154034736988190
今日推荐