How I give space between 4 digits ?
Want help to solve issue
How I give space between 4 digits ?
Want help to solve issue
Try below code hope its helpful to you.
Your Widget:
TextFormField(
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
CardNumberFormatter(),
],
textInputAction: TextInputAction.done,
keyboardType: TextInputType.number,
decoration: InputDecoration(
prefixIcon: Padding(
padding: const EdgeInsets.all(8.0),
child: Image.network(
'https://upload.wikimedia.org/wikipedia/commons/thumb/2/2a/Mastercard-logo.svg/800px-Mastercard-logo.svg.png',
height: 30,
width: 30,
),
),
suffixIcon: const Padding(
padding: EdgeInsets.all(8.0),
child: Text(
'Change',
style: TextStyle(color: Colors.green),
),
),
border: const OutlineInputBorder(),
hintText: 'XXXX XXXX XXXX XXXX',
labelText: 'Card Number',
),
maxLength: 19,
onChanged: (value) {},
),
Create class for seprate the digits:
class CardNumberFormatter extends TextInputFormatter {
@override
TextEditingValue formatEditUpdate(
TextEditingValue previousValue,
TextEditingValue nextValue,
) {
var inputText = nextValue.text;
if (nextValue.selection.baseOffset == 0) {
return nextValue;
}
var bufferString = StringBuffer();
for (int i = 0; i < inputText.length; i++) {
bufferString.write(inputText[i]);
var nonZeroIndexValue = i + 1;
if (nonZeroIndexValue % 4 == 0 && nonZeroIndexValue != inputText.length) {
bufferString.write(' ');
}
}
var string = bufferString.toString();
return nextValue.copyWith(
text: string,
selection: TextSelection.collapsed(
offset: string.length,
),
);
}
}
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() {
runApp(
MyApp(),
);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: MyWidget(),
),
),
);
}
}
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
margin: const EdgeInsets.symmetric(
horizontal: 20,
),
child: TextFormField(
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
CardNumberFormatter(),
],
textInputAction: TextInputAction.done,
keyboardType: TextInputType.number,
decoration: InputDecoration(
prefixIcon: Padding(
padding: const EdgeInsets.all(8.0),
child: Image.network(
'https://upload.wikimedia.org/wikipedia/commons/thumb/2/2a/Mastercard-logo.svg/800px-Mastercard-logo.svg.png',
height: 30,
width: 30,
),
),
suffixIcon: const Padding(
padding: EdgeInsets.all(8.0),
child: Text(
'Change',
style: TextStyle(color: Colors.green),
),
),
border: const OutlineInputBorder(),
hintText: 'XXXX XXXX XXXX XXXX',
labelText: 'Card Number',
),
maxLength: 19,
onChanged: (value) {},
),
);
}
}
class CardNumberFormatter extends TextInputFormatter {
@override
TextEditingValue formatEditUpdate(
TextEditingValue previousValue,
TextEditingValue nextValue,
) {
var inputText = nextValue.text;
if (nextValue.selection.baseOffset == 0) {
return nextValue;
}
var bufferString = StringBuffer();
for (int i = 0; i < inputText.length; i++) {
bufferString.write(inputText[i]);
var nonZeroIndexValue = i + 1;
if (nonZeroIndexValue % 4 == 0 && nonZeroIndexValue != inputText.length) {
bufferString.write(' ');
}
}
var string = bufferString.toString();
return nextValue.copyWith(
text: string,
selection: TextSelection.collapsed(
offset: string.length,
),
);
}
}
Test Your code on Darpad
The selected answer didn't work for me. But here is my own version of the problem, which also has a custom separator hope it helps someone out there.
Make sure you clean the card number and remove the separators inside the card number validator in your TextField
. So Instead of passing the basic value with all the separators inside it, make sure you use something like
validator: (val) {
/// check if it is null empty or whitespace
if (val == null || val.isEmpty || val.trim().isEmpty) {
return "Please input card number";
}
var cleanCardNumber = val.replaceAll(separator, '');
if (_validateCard(cleanCardNumber)) {
return "invalid card number";
}
},
class CardFormatter extends TextInputFormatter {
final String separator;
CardFormatter({required this.separator});
@override
TextEditingValue formatEditUpdate(
TextEditingValue oldValue, TextEditingValue newValue) {
var oldS = oldValue.text;
var newS = newValue.text;
var endsWithSeparator = false;
// if you add text
if (newS.length > oldS.length) {
for (var char in separator.characters) {
if (newS.substring(0, newS.length - 1).endsWith(char)) {
endsWithSeparator = true;
}
}
print(
'Ends with separator: $endsWithSeparator, so we will add it with next digit.');
var clean = newS.replaceAll(separator, '');
print('CLEAN add: $clean');
if (!endsWithSeparator && clean.length > 1 && clean.length % 4 == 1) {
return newValue.copyWith(
text: newS.substring(0, newS.length - 1) +
separator +
newS.characters.last,
selection: TextSelection.collapsed(
offset: newValue.selection.end + separator.length,
),
);
}
}
// if you delete text
if (newS.length < oldS.length) {
for (var char in separator.characters) {
if (oldS.substring(0, oldS.length - 1).endsWith(char)) {
endsWithSeparator = true;
}
}
print('Ends with separator: $endsWithSeparator, so we removed it');
var clean = oldS.substring(0, oldS.length - 1).replaceAll(separator, '');
print('CLEAN remove: $clean');
if (endsWithSeparator && clean.isNotEmpty && clean.length % 4 == 0) {
return newValue.copyWith(
text: newS.substring(0, newS.length - separator.length),
selection: TextSelection.collapsed(
offset: newValue.selection.end - separator.length,
),
);
}
}
return newValue;
}
}
keyboardType
keyboardType: TextInputType.number,
inputFormatters
inside the TextFormField
Widget// somewhere inside the code define the separator
var separator = ' - ';
[...]
// and add this to your `TextFormField` Widget
inputFormatters: [
/// allows card number length of 18 and 4 separators
LengthLimitingTextInputFormatter(18 + separator.length * 4),
CardFormatter(separator: separator),
],
Hope this helps and works for you as well, feel free to change the text input limit to whatever you need. But if you do, also take into account the number of separators you would like to have.
In this article I found a simple solution, all what you need to do is create the class below and assign it to your TextField
widget:
1- Create this class:
class CreditCardNumberFormatter extends TextInputFormatter {
@override
TextEditingValue formatEditUpdate(TextEditingValue oldValue, TextEditingValue newValue) {
if(newValue.selection.baseOffset == 0) {
return newValue;
}
String enteredData = newValue.text; // get data enter by used in textField
StringBuffer buffer = StringBuffer();
for (int i = 0;i < enteredData.length;i++) {
// add each character into String buffer
buffer.write(enteredData[i]);
int index = i + 1;
if(index % 4 == 0 && enteredData.length != index) {
// add space after 4th digit
buffer.write(' ');
}
}
return TextEditingValue(
text: buffer.toString(), // final generated credit card number
selection: TextSelection.collapsed(offset: buffer.toString().length) // keep the cursor at end
);
}
}
2- Assign the new class to inputFormatters inside TextField:
TextField(
// ..
inputFormatters: [
LengthLimitingTextInputFormatter(16),
CreditCardNumberFormatter()
],
// ..
),
© 2022 - 2024 — McMap. All rights reserved.