inputFormatter should allow just decimal numbers and negative numbers

2.4k views Asked by At

I want to allow users to just adding numbers "12345" and decimal numbers like "21321.12312" and negative numbers like -23423.32432. Users shouldn't be able to add multiple "." like "12..32" and add "-" just in first of input like -324.34 not like 324-4323. I used this regEx r'^(-?\d+\.\d+)(\s*,\s*-?\d+\.\d+)+$' but can't enter anything.

TextField code:

TextFormField(
          inputFormatters: [
            FilteringTextInputFormatter.allow(
                RegExp(r'^(-?\d+\.\d+)(\s*,\s*-?\d+\.\d+)+$')),
          ],
          controller: budget,
          keyboardType: TextInputType.number,
          decoration: InputDecoration(
            contentPadding:
                EdgeInsets.only(right: 20, left: 20, top: 10, bottom: 10),
            hintText: getTranslated(context, "budget_example"),
            hintStyle: TextStyle(fontSize: 13, fontFamily: "tahoma"),
            border: OutlineInputBorder(
              borderSide: BorderSide(width: 1, color: MyColors.secondary),
              borderRadius: BorderRadius.circular(100),
            ),
          ),
        ),
1

There are 1 answers

0
Mohammad_Asef On BEST ANSWER

Allow only 1 .

Allow negative

Place negative sign on beginning

We should create our own input formatter

import 'package:flutter/services.dart';

class NumberTextInputFormatter extends TextInputFormatter {
  NumberTextInputFormatter({this.decimalRange}) : assert(decimalRange == null || decimalRange > 0);

  final int decimalRange;

  @override
  TextEditingValue formatEditUpdate(TextEditingValue oldValue, TextEditingValue newValue) {
    TextEditingValue _newValue = this.sanitize(newValue);
    String text = _newValue.text;

    if (decimalRange == null) {
      return _newValue;
    }

    if (text == '.') {
      return TextEditingValue(
        text: '0.',
        selection: _newValue.selection.copyWith(baseOffset: 2, extentOffset: 2),
        composing: TextRange.empty,
      );
    }

    return this.isValid(text) ? _newValue : oldValue;
  }

  bool isValid(String text) {
    int dots = '.'.allMatches(text).length;

    if (dots == 0) {
      return true;
    }

    if (dots > 1) {
      return false;
    }

    return text.substring(text.indexOf('.') + 1).length <= decimalRange;
  }

  TextEditingValue sanitize(TextEditingValue value) {
    if (false == value.text.contains('-')) {
      return value;
    }

    String text = '-' + value.text.replaceAll('-', '');

    return TextEditingValue(text: text, selection: value.selection, composing: TextRange.empty);
  }
}

and (don't forget to import the previous class)

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

class NumberFormField extends StatelessWidget {
  final InputDecoration decoration;
  final TextEditingController controller;
  final int decimalRange;

  const NumberFormField({Key key, this.decoration, this.controller, this.decimalRange}) :super(key: key);

  @override
  Widget build(BuildContext context) {
    return TextFormField(
      decoration: this.decoration,
      controller: this.controller,
      keyboardType: TextInputType.numberWithOptions(decimal: true),
      inputFormatters: [
        WhitelistingTextInputFormatter(RegExp(r'[\d+\-\.]')),
        NumberTextInputFormatter(decimalRange: this.decimalRange),
      ],
    );
  }
}