13
votes

Autoriser seulement deux nombres décimaux dans l'entrée flottante?

Je veux seulement deux chiffres après la virgule décimale dans l'entrée flutter. L'utilisateur ne peut pas ajouter plus de deux chiffres après la virgule décimale.


6 commentaires

Vous pouvez utiliser TextEditingController pour écouter les entrées et y gérer votre logique.


Il n'y a donc aucune possibilité de format d'entrée. Par exemple, inputFormatters: (keyboardType == TextInputType.number)? [WhitelistingTextInputFormatter.digitsOnly]: [],


Pour autant que je puisse dire, non, ils ne vous aideront pas, ils ne peuvent vous donner que des options pour choisir un type de clavier spécifique.


Merci beaucoup, je ne sais pas pourquoi cette question a obtenu -2 points.


Probablement parce que vous n'avez montré aucun code que vous avez essayé et que personne n'écrira une solution pour vous à partir de zéro.


Vous devriez mettre à jour la réponse, j'en ai trouvé une plus simple.


9 Réponses :


29
votes

Voici! J'espère que cela aide :)

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

import 'dart:math' as math;

void main() {
  runApp(new MaterialApp(home: new MyApp()));
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Flutter"),
      ),
      body: Form(
        child: ListView(
          children: <Widget>[
            TextFormField(
              inputFormatters: [DecimalTextInputFormatter(decimalRange: 2)],
              keyboardType: TextInputType.numberWithOptions(decimal: true),
            )
          ],
        ),
      ),
    );
  }
}

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

  final int decimalRange;

  @override
  TextEditingValue formatEditUpdate(
    TextEditingValue oldValue, // unused.
    TextEditingValue newValue,
  ) {
    TextSelection newSelection = newValue.selection;
    String truncated = newValue.text;

    if (decimalRange != null) {
      String value = newValue.text;

      if (value.contains(".") &&
          value.substring(value.indexOf(".") + 1).length > decimalRange) {
        truncated = oldValue.text;
        newSelection = oldValue.selection;
      } else if (value == ".") {
        truncated = "0.";

        newSelection = newValue.selection.copyWith(
          baseOffset: math.min(truncated.length, truncated.length + 1),
          extentOffset: math.min(truncated.length, truncated.length + 1),
        );
      }

      return TextEditingValue(
        text: truncated,
        selection: newSelection,
        composing: TextRange.empty,
      );
    }
    return newValue;
  }
}


4 commentaires

@AjayKumar le code 'math.min (truncated.length, truncated.length + 1)' semble assez redondant.


Le problème avec ceci est de forcer un "." ne prend pas en charge les paramètres régionaux qui intervertissent les points et les virgules.


@AjayKumar Merci, a travaillé pour moi. Sur certains claviers, il est nécessaire de cliquer sur le point pour ajouter un signe moins. Dans cette classe, vous pouvez entrer moins après avoir entré toutes les valeurs. J'ajouterai si je vérifie cela. Merci encore.


Si l'utilisateur ajoute plus de nombres après les décimales, la suppression ne fonctionne pas avant d'atteindre les deux premiers nombres.



0
votes

J'ai étendu les fonctionnalités ... J'espère que vous pourrez le trouver utile. Dites-moi si vous pouvez vous améliorer encore plus s'il vous plaît.

import 'package:flutter/services.dart';
import 'dart:math' as math;

class DecimalTextInputFormatter extends TextInputFormatter {
  DecimalTextInputFormatter({this.decimalRange, this.activatedNegativeValues})
      : assert(decimalRange == null || decimalRange >= 0,
            'DecimalTextInputFormatter declaretion error');

  final int decimalRange;
  final bool activatedNegativeValues;

  @override
  TextEditingValue formatEditUpdate(
    TextEditingValue oldValue, // unused.
    TextEditingValue newValue,
  ) {
    TextSelection newSelection = newValue.selection;
    String truncated = newValue.text;


if (newValue.text.contains(' ')) {
  return oldValue;
}

if (newValue.text.isEmpty) {
  return newValue;
} else if (double.tryParse(newValue.text) == null &&
    !(newValue.text.length == 1 &&
        (activatedNegativeValues == true ||
            activatedNegativeValues == null) &&
        newValue.text == '-')) {
  return oldValue;
}

if (activatedNegativeValues == false &&
    double.tryParse(newValue.text) < 0) {
  return oldValue;
}

if (decimalRange != null) {
  String value = newValue.text;

  if (decimalRange == 0 && value.contains(".")) {
    truncated = oldValue.text;
    newSelection = oldValue.selection;
  }

  if (value.contains(".") &&
      value.substring(value.indexOf(".") + 1).length > decimalRange) {
    truncated = oldValue.text;
    newSelection = oldValue.selection;
  } else if (value == ".") {
    truncated = "0.";

    newSelection = newValue.selection.copyWith(
      baseOffset: math.min(truncated.length, truncated.length + 1),
      extentOffset: math.min(truncated.length, truncated.length + 1),
    );
  }

  return TextEditingValue(
    text: truncated,
    selection: newSelection,
    composing: TextRange.empty,
  );
}
return newValue;
}
}


2 commentaires

les solutions ici sont plutôt bonnes. Je pense que ce serait encore mieux si la virgule était incluse lors du formatage par milliers.


Bonjour Monsieur! Il est possible d'ajouter un format numérique à votre code avec decimalRange max 2? Je veux réaliser ceci: "100,25" "1 000,25" "10 000,25"



6
votes

Une version plus courte de DecimalTextInputFormatter utilisant Regexp:

class DecimalTextInputFormatter extends TextInputFormatter {

  DecimalTextInputFormatter({int decimalRange, bool activatedNegativeValues})
  : assert(decimalRange == null || decimalRange >= 0,
    'DecimalTextInputFormatter declaretion error') {
    String dp = (decimalRange != null && decimalRange > 0) ? "([.][0-9]{0,$decimalRange}){0,1}" : "";
    String num = "[0-9]*$dp";

    if(activatedNegativeValues) {
      _exp = new RegExp("^((((-){0,1})|((-){0,1}[0-9]$num))){0,1}\$");
    }
    else {
      _exp = new RegExp("^($num){0,1}\$");
    }
  }

  RegExp _exp;

  @override
  TextEditingValue formatEditUpdate(
    TextEditingValue oldValue,
    TextEditingValue newValue,
  ) {
    if(_exp.hasMatch(newValue.text)){
      return newValue;
    }
    return oldValue;
  }
}


1 commentaires

Merci, ce code ignore également les lettres et les symboles, ne laissant que des chiffres et un point.



0
votes

La réponse de @AjayKumar permet de limiter la saisie de texte aux décimales requises, mais mon exigence était d'éviter un autre caractère du clavier à l'exception du nombre et d'un point.J'ai donc mis à jour la réponse ci-dessus de @ AjayKumar

import 'package:flutter/services.dart';
import 'dart:math' as math;   

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

final int decimalRange;

@override
TextEditingValue formatEditUpdate(
TextEditingValue oldValue, // unused.
TextEditingValue newValue,
) {
TextSelection newSelection = newValue.selection;
String truncated = newValue.text;

if (decimalRange != null) {
  String value = newValue.text;

  if (value.contains(',') ||
      value.contains('-') ||
      value.contains(' ') ||
      value.contains('..')) {
    truncated = oldValue.text;
    newSelection = oldValue.selection;
  } else if (value.contains(".") &&
      value.substring(value.indexOf(".") + 1).length > decimalRange) {
    truncated = oldValue.text;
    newSelection = oldValue.selection;
  } else if (value == ".") {
    truncated = "0.";

    newSelection = newValue.selection.copyWith(
      baseOffset: math.min(truncated.length, truncated.length + 1),
      extentOffset: math.min(truncated.length, truncated.length + 1),
    );
  }

  return TextEditingValue(
    text: truncated,
    selection: newSelection,
    composing: TextRange.empty,
  );
}
return newValue;

}}


0 commentaires

2
votes

Peut-être un peu en retard pour vous, mais j'ai aussi amélioré un peu:

  1. Autoriser seulement 1 .
  2. Autoriser le négatif
  3. Placer un signe négatif au début

J'espère que cela aide ;)

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),
      ],
    );
  }
}

et (n'oubliez pas d'importer la classe précédente)

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);
  }
}


0 commentaires

0
votes

Et en évitant les zéros inutiles ... Veuillez déboguer ce code.

import 'dart:math' as math;

import 'package:flutter/services.dart';

class DecimalTextInputFormatter extends TextInputFormatter {
  DecimalTextInputFormatter({this.decimalRange, this.activatedNegativeValues})
      : assert(decimalRange == null || decimalRange >= 0,
            'DecimalTextInputFormatter declaretion error');

  final int decimalRange;
  final bool activatedNegativeValues;

  @override
  TextEditingValue formatEditUpdate(
    TextEditingValue oldValue, // unused.
    TextEditingValue newValue,
  ) {
    TextSelection newSelection = newValue.selection;
    String truncated = newValue.text;

    if (newValue.text.contains(' ')) {
      return oldValue;
    }

    if (newValue.text.isEmpty) {
      return newValue;
    } else if (double.tryParse(newValue.text) == null &&
        !(newValue.text.length == 1 &&
            (activatedNegativeValues == true ||
                activatedNegativeValues == null) &&
            newValue.text == '-')) {
      return oldValue;
    }

    if (activatedNegativeValues == false &&
        double.tryParse(newValue.text) < 0) {
      return oldValue;
    }

    if ((double.tryParse(oldValue.text) == 0 && !newValue.text.contains('.'))) {
      if (newValue.text.length >= oldValue.text.length) {
        return oldValue;
      }
    }

    if (decimalRange != null) {
      String value = newValue.text;

      if (decimalRange == 0 && value.contains(".")) {
        truncated = oldValue.text;
        newSelection = oldValue.selection;
      }

      if (value.contains(".") &&
          value.substring(value.indexOf(".") + 1).length > decimalRange) {
        truncated = oldValue.text;
        newSelection = oldValue.selection;
      } else if (value == ".") {
        truncated = "0.";

        newSelection = newValue.selection.copyWith(
          baseOffset: math.min(truncated.length, truncated.length + 1),
          extentOffset: math.min(truncated.length, truncated.length + 1),
        );
      }

      return TextEditingValue(
        text: truncated,
        selection: newSelection,
        composing: TextRange.empty,
      );
    }
    return newValue;
  }
}


0 commentaires

14
votes

Voici une solution qui fonctionne pour moi

TextFormField(
    inputFormatters: [
        WhitelistingTextInputFormatter(RegExp(r'^(\d+)?\.?\d{0,2}')),
    ],
)

Si vous souhaitez autoriser une entrée comme (.21) ou (.25)

Voici une solution-

TextFormField(
    inputFormatters: [
        WhitelistingTextInputFormatter(RegExp(r'^\d+\.?\d{0,2}')),
    ],
)


1 commentaires

Votre solution permet à un utilisateur de saisir des points supplémentaires dans la partie entière



1
votes

C'est peut-être une solution plus simple

inputFormatters: [
            FilteringTextInputFormatter.allow(RegExp(r'(^\d*\.?\d{0,2})'))
          ]


1 commentaires

pouvez-vous spécifier ce qui est mieux par rapport à l'autre réponse qui utilise l'expression régulière?



1
votes

après Flutter Version v1.20.0-1.0. utilisation
TextFormField(
  keyboardType: TextInputType.numberWithOptions(decimal: true),
  inputFormatters: [
    FilteringTextInputFormatter.allow(RegExp(r'^\d+\.?\d{0,2}')),
  ],
),


0 commentaires