import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; /// Format: "dd/mm/yyyy" class DateInputFormatter extends TextInputFormatter { @override TextEditingValue formatEditUpdate( TextEditingValue oldValue, TextEditingValue newValue) { if (newValue.text.isEmpty) { return newValue; } String newText = _formatDate(newValue.text, oldValue.text); return newValue.copyWith( text: newText, // Problem: If the user edits the middle of the String, the cursor is moved to the end. selection: TextSelection.collapsed(offset: newText.length), ); } String _formatDate(String text, String oldText) { // Remove non-numeric characters text = text.replaceAll(RegExp(r'[^0-9]'), ''); if (text.length > 8) { text = text.substring(0, 8); } final buffer = StringBuffer(); for (var i = 0; i < text.length; i++) { buffer.write(text[i]); if (i == 1 || i == 3) { buffer.write('/'); } } String newText = buffer.toString(); // Remove the '/' if backspace is pressed if ((newText.length == 3 || newText.length == 6) && (newText.length == oldText.length)) { newText = newText.substring(0, newText.length - 1); } return newText; } } /// Format: "dd/xxxx..." class ExpiryDateFormatter extends TextInputFormatter { String prevValue = ''; @override TextEditingValue formatEditUpdate( TextEditingValue oldValue, TextEditingValue newValue) { String text = newValue.text; if (text.length == 3) { if (text.length > prevValue.length) { final cursorPosition = newValue.selection; newValue = newValue.copyWith( text: '${text.substring(0, 2)}/${text.substring(2)}', selection: TextSelection.collapsed(offset: cursorPosition.extentOffset + 1), ); } else { final cursorPosition = newValue.selection; newValue = newValue.copyWith( text: text.substring(0, 2), selection: TextSelection.collapsed( offset: cursorPosition.extentOffset - 1)); } } prevValue = newValue.text; return newValue; } }