dmz社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 3183|回复: 2

[混合APP] flutter通过TextInputFormatter实现限制数字输入

[复制链接]

88

主题

133

帖子

676

积分

荣誉会员

积分
676

发表于 2023-3-13 23:22:47 | 显示全部楼层 |阅读模式

本站资源全部免费,回复即可查看下载地址!

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
背景
在开发中经常会遇到需要对输入的数字限制的需求,比如限制输入几位小数,或者只能输入整数,或者支持负数。。。


实现类

[JavaScript] 纯文本查看 复制代码
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
/*
 * @Author: zhudaihao
 * @Date: 2022/2/25
 * @Describe: 限制输入数字和小数后位数
 */
class NumberInputLimit extends TextInputFormatter {
  ///输入字符的范围
  String inputScope;

  ///允许的小数位数
  final int? digit;

  ///允许的最大值
  final double? max;

  ///是否支持 false不支持负数(默认不支持)
  final bool isNegative;

  NumberInputLimit({
    this.inputScope = '-.0123456789',
    this.digit,
    this.max,
    this.isNegative = false,
  });

  ///获取value小数点后有几位
  static int getDecimalAfterLength(String value) {
    if (value.contains(".")) {
      return value.split(".")[1].length;
    } else {
      return 0;
    }
  }

  @override
  TextEditingValue formatEditUpdate(
      TextEditingValue oldValue, TextEditingValue newValue) {
    //上次文本
    String oldContent = oldValue.text;
    //最新文本
    String newContent = newValue.text;
    //上次文本长度
    int oldLength = oldContent.length;
    //最新文本长度
    int newLength = newContent.length;
    //上次文本光标位置
    int oldBaseOffset = oldValue.selection.baseOffset;
    //最新文本光标位置
    int newBaseOffset = newValue.selection.baseOffset;
    //光标位置
    int offset = newBaseOffset;

    if (newLength > oldLength) {
      //输入的字符
      String inputContent = newContent.substring(oldBaseOffset, newBaseOffset);
      if (!isNegative) {
        inputScope = inputScope.replaceAll("-", "");
      }
      if (inputScope.contains(inputContent)) {
        if (oldLength > 0) {
          if ((max != null && double.parse(newContent) > max!) ||
              (digit != null && getDecimalAfterLength(newContent) > digit!)) {
            newContent = oldContent;
            offset = oldBaseOffset;
          } else if (oldContent.substring(0, 1) == "-") {
            //上次文本首字符是-
            if ((oldContent.contains(".") && inputContent == ".") ||
                inputContent == "-" ||
                (oldContent.contains(".") &&
                    newLength > 2 &&
                    newContent.substring(2, 3) != "." &&
                    newContent.substring(1, 2) == "0") ||
                (newLength > 2 && newContent.substring(0, 3) == "-00") ||
                (newLength > 2 &&
                    !newContent.contains(".") &&
                    newContent.substring(1, 2) == "0") ||
                (oldContent.substring(0, 1) == "-" &&
                    newContent.substring(0, 1) != "-")) {
              newContent = oldContent;
              offset = oldBaseOffset;
            }
          } else if (oldContent.substring(0, 1) == "0") {
            //上次文本首字符是0
            if (newLength > 1 && newContent.substring(0, 2) == "00" ||
                (newContent.contains("-") &&
                    newContent.substring(0, 1) != "-") ||
                (oldContent.contains(".") && inputContent == ".") ||
                (newContent.substring(0, 1) == "0" &&
                    newLength > 1 &&
                    newContent.substring(1, 2) != ".")) {
              newContent = oldContent;
              offset = oldBaseOffset;
            }
          } else if (newContent.contains(".")) {
            //上次文本首字符是.
            if ((oldLength > 1 &&
                oldContent.substring(0, 2) == "0." &&
                inputContent == ".") ||
                (newContent.substring(0, 1) != "-" &&
                    newContent.contains("-")) ||
                (oldContent.contains(".") && inputContent == ".") ||
                (oldContent.contains(".") &&
                    oldContent.substring(0, 1) != "." &&
                    newContent.substring(0, 1) == "0")) {
              newContent = oldContent;
              offset = oldBaseOffset;
            }
          }
        }
      } else {
        //输入限制范围外字符
        newContent = oldContent;
        offset = oldBaseOffset;
      }
    }

    return TextEditingValue(
      text: newContent,
      selection: TextSelection.collapsed(offset: offset),
    );
  }
}



使用代码
[JavaScript] 纯文本查看 复制代码
Scaffold(
  appBar: AppBar(
    title: const Text("测试编辑限制"),
  ),
  body: Material(
    child: Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        const Text("不限制"),
        Padding(
          padding: const EdgeInsets.all(8.0),
          child: TextField(
            decoration: const InputDecoration(hintText: "请输入"),
            inputFormatters: [
              NumberInputLimit(),
            ],
          ),
        ),
        const Text("支持负数"),
        Padding(
          padding: const EdgeInsets.all(8.0),
          child: TextField(
            decoration: const InputDecoration(hintText: "请输入"),
            inputFormatters: [
              //限制小数位数
              NumberInputLimit(
                isNegative: true,
              ),
            ],
          ),
        ),
        const Text("限制输入最大值100"),
        Padding(
          padding: const EdgeInsets.all(8.0),
          child: TextField(
            decoration: const InputDecoration(hintText: "请输入"),
            inputFormatters: [
              //限制小数位数
              NumberInputLimit(
                max: 100,
              ),
            ],
          ),
        ),
        const Text("限制输入小数点2位"),
        Padding(
          padding: const EdgeInsets.all(8.0),
          child: TextField(
            decoration: const InputDecoration(hintText: "请输入"),
            inputFormatters: [
              //限制小数位数
              NumberInputLimit(
                digit: 2,
              ),
            ],
          ),
        ),
        const Text("限制输入所有字符范围"),
        Padding(
          padding: const EdgeInsets.all(8.0),
          child: TextField(
            decoration: const InputDecoration(hintText: "请输入"),
            inputFormatters: [
              //限制小数位数
              NumberInputLimit(
                inputScope: "123456",
              ),
            ],
          ),
        ),
      ],
    ),
  ),
)

回复

使用道具 举报

1

主题

5618

帖子

1万

积分

超凡入圣

Rank: 10Rank: 10Rank: 10

积分
16923

发表于 2023-3-15 08:28:17 | 显示全部楼层
1111111111111111
回复 支持 反对

使用道具 举报

1

主题

5618

帖子

1万

积分

超凡入圣

Rank: 10Rank: 10Rank: 10

积分
16923

发表于 2023-3-26 08:30:19 | 显示全部楼层
44444444444444444
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|小黑屋|dmz社区

GMT+8, 2026-7-29 03:55 , Processed in 0.046845 second(s), 11 queries , Redis On.

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表