Flutter中如何限制连续两个点输入?基于TextInputFormField实现规范小数输入
Got it, let's fix this input issue for you. You want to stop users from entering things like 1.. and enforce clean decimal formats like 1.23 using a formatter with TextInputFormField—here's a straightforward, customizable approach:
Step 1: Build a Custom Decimal Input Formatter
Instead of relying on a generic formatter, let's create one that explicitly blocks consecutive dots and enforces your desired decimal rules. This gives you full control over the input behavior:
class ValidDecimalFormatter extends TextInputFormatter { final int maxDecimalPlaces; ValidDecimalFormatter({this.maxDecimalPlaces = 2}); @override TextEditingValue formatEditUpdate( TextEditingValue oldValue, TextEditingValue newValue) { String inputText = newValue.text; // Handle empty input if (inputText.isEmpty) return newValue; // Block multiple decimal points (e.g., turn "1..2" into "1.2") if (inputText.contains('.')) { final parts = inputText.split('.'); if (parts.length > 2) { inputText = '${parts[0]}.${parts.sublist(1).join()}'; } // Limit decimal places to your desired count if (parts.length == 2 && parts[1].length > maxDecimalPlaces) { inputText = '${parts[0]}.${parts[1].substring(0, maxDecimalPlaces)}'; } } // Prevent invalid leading zeros (e.g., "0012.34" becomes "12.34") if (inputText.startsWith('0') && inputText.length > 1 && !inputText.startsWith('0.')) { inputText = inputText.substring(1); } return TextEditingValue( text: inputText, selection: TextSelection.collapsed(offset: inputText.length), ); } }
Step 2: Integrate the Formatter into Your TextInputFormField
Now plug this formatter into your field, along with basic validation to ensure the final input is a valid number:
TextInputFormField( keyboardType: TextInputType.numberWithOptions(decimal: true), inputFormatters: [ // Regex to allow only digits, one decimal point, and up to 2 decimals FilteringTextInputFormatter.allow(RegExp(r'^\d+\.?\d{0,2}')), ValidDecimalFormatter(maxDecimalPlaces: 2), // Our custom formatter ], decoration: InputDecoration( labelText: 'Enter Decimal Number', border: OutlineInputBorder(), ), validator: (value) { if (value == null || value.isEmpty) { return 'Please enter a number'; } if (double.tryParse(value) == null) { return 'Enter a valid decimal number (e.g., 1.23)'; } return null; }, )
Key Features Breakdown
- Blocks consecutive dots: Automatically cleans up inputs like
1..5to1.5as the user types. - Adjustable decimal limits: Change
maxDecimalPlacesto allow more/less decimal digits (e.g., 3 for1.234). - Clean leading zeros: Stops messy inputs like
000.45from being entered.
Alternative: Using a Pre-built Decimal Formatter
If you prefer using an existing package formatter (like from flutter_form_builder), you can combine it with our custom logic to cover the consecutive dot edge case:
// Add flutter_form_builder to your pubspec.yaml first TextInputFormField( keyboardType: TextInputType.numberWithOptions(decimal: true), inputFormatters: [ DecimalInputFormatter(decimalRange: 2, enabledNegative: false), ValidDecimalFormatter(maxDecimalPlaces: 2), // Adds the consecutive dot block ], // Rest of your field properties... )
内容的提问来源于stack exchange,提问作者Jaya kumar

