Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save AleksandarSavic95/a1128f99393f61f0d0ebea6740fb153f to your computer and use it in GitHub Desktop.
Save AleksandarSavic95/a1128f99393f61f0d0ebea6740fb153f to your computer and use it in GitHub Desktop.
Flutter TextInputFormatter for credit card number and expiry date
// Modified from https://youtu.be/4v4l6E8Sbj8?t=1025 (at around 17:05)
import 'package:flutter/services.dart';
/// A [TextInputFormatter] for the credit card number. Adds space after every four characters.
class CreditCardInputFormatter extends TextInputFormatter {
final separator = ' ';
@override
TextEditingValue formatEditUpdate(TextEditingValue oldValue, TextEditingValue newValue) {
return textManipulation(
oldValue,
newValue,
textInputFormatter: FilteringTextInputFormatter.digitsOnly,
formatPattern: (filteredString) {
var buffer = StringBuffer();
for (var i = 0; i < filteredString.length; i++) {
buffer.write(filteredString[i]);
if ((i + 1) % 4 == 0) {
buffer.write(separator);
}
}
return buffer.toString();
},
);
}
}
/// A [TextInputFormatter] for the expiry date of a credit card. Adds " / " after the first two characters.
class ExpiryDateInputFormatter extends TextInputFormatter {
final separator = ' / ';
@override
TextEditingValue formatEditUpdate(TextEditingValue oldValue, TextEditingValue newValue) {
return textManipulation(
oldValue,
newValue,
textInputFormatter: FilteringTextInputFormatter.digitsOnly,
formatPattern: (filteredString) {
return filteredString.length >= 2
? filteredString.substring(0, 2) + separator + filteredString.substring(2, filteredString.length)
: filteredString;
},
);
}
}
TextEditingValue textManipulation(
TextEditingValue oldValue,
TextEditingValue newValue, {
required String Function(String filteredString) formatPattern,
required TextInputFormatter textInputFormatter,
}) {
// Remove all invalid characters
newValue = textInputFormatter.formatEditUpdate(oldValue, newValue);
var cursorPosition = newValue.selection.end;
print(cursorPosition);
final textWithSeparators = formatPattern(newValue.text);
if (textWithSeparators == newValue.text) {
return newValue;
}
bool isUserInput(String s) => newValue.text.contains(s);
// Count number of inserted characters in the new string (up until the current cursor position)
int insertedCharactersCount = 0;
int initialCharactersCount = 0;
for (var i = 0; i < textWithSeparators.length && initialCharactersCount < cursorPosition; i++) {
final character = textWithSeparators[i];
if (isUserInput(character)) {
initialCharactersCount++;
} else {
insertedCharactersCount++;
}
}
// Adjust cursor position according to number of inserted characters
cursorPosition += insertedCharactersCount;
return newValue.copyWith(
text: textWithSeparators,
selection: TextSelection.collapsed(offset: cursorPosition),
composing: TextRange.empty,
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment