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: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'Change',
style: TextStyle(color: Colors.green),
),
),
border: 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 = new 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: new TextSelection.collapsed(
offset: string.length,
),
);
}
}
Full Example:
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: 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: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'Change',
style: TextStyle(color: Colors.green),
),
),
border: 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 = new 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: new 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 inside the car 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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.