I am trying to make a text field that properly formats a phone number. I have tried using
NumberFormat(\"+# ### ### ####\");
But it doesn\'t ret
Here's a light weight approach (does not work correctly on older Android OS KitKit) where you can set the specific format you want with the MaskedInputFormater class, using the plugin: flutter_multi_formatter
import 'package:flutter_multi_formatter/flutter_multi_formatter.dart';
TextFormField(
keyboardType: TextInputType.phone,
autocorrect: false,
inputFormatters: [
MaskedInputFormater('(###) ###-####')
],
// .. etc
);
In my case, app is only domestic to start, so I don't want any international code in the phone number UI. All the plugins out there seem to expect that.
========================
Update 1
Just tested this on the older Android KitKat, and unfortunately doesn't work correctly there.
However, depending on the app and the audience - if you know most users will have a later OS, this is not a bad solution for getting something out there.
Use the intl_phone_number_input
package from pub.dev
. I think it's easy.
follow this link
(US only but easily modifiable) I would recommend only storing digits in your model and formatting the number specifically for the view. For that, I did the following:
/// Human readable version of the phone number
String getFormattedPhoneNumber() {
if (_phoneNumber.isEmpty) {
return "";
}
String phoneNumber = _phoneNumber;
bool addPlus = phoneNumber.startsWith("1");
if (addPlus) phoneNumber = phoneNumber.substring(1);
bool addParents = phoneNumber.length >= 3;
bool addDash = phoneNumber.length >= 8;
// +1
String updatedNumber = "";
if (addPlus) updatedNumber += "+1";
// (222)
if (addParents) {
updatedNumber += "(";
updatedNumber += phoneNumber.substring(0, 3);
updatedNumber += ")";
} else {
updatedNumber += phoneNumber.substring(0);
return updatedNumber;
}
// 111
if (addDash) {
updatedNumber += phoneNumber.substring(3, 6);
updatedNumber += "-";
} else {
updatedNumber += phoneNumber.substring(3);
return updatedNumber;
}
// 3333
updatedNumber += phoneNumber.substring(6);
return updatedNumber;
}
And in your TextInput onChanged method:
void setPhoneNumber(String phoneNumber) {
if (phoneNumber.contains("\(") && !phoneNumber.contains("\)")) {
// Remove the digit the user wanted to remove but couldn't b/c a paren
// was in the way.
phoneNumber = phoneNumber.substring(0, phoneNumber.length - 1);
}
// Only store the actual digits
phoneNumber = phoneNumber.replaceAll(RegExp("[^0-9]"), "");
// Don't let the user enter more digits than is possible
int maxLength = phoneNumber.startsWith("1") ? 11 : 10;
if (phoneNumber.length > maxLength) {
phoneNumber = phoneNumber.substring(0, maxLength);
}
model.setPhoneNumber(phoneNumber);
// Notify the UI to update based on new input
notifyListeners();
}
This Should Work :
class NumberTextInputFormatter extends TextInputFormatter {
@override
TextEditingValue formatEditUpdate(
TextEditingValue oldValue, TextEditingValue newValue) {
final int newTextLength = newValue.text.length;
int selectionIndex = newValue.selection.end;
int usedSubstringIndex = 0;
final StringBuffer newText = new StringBuffer();
if (newTextLength >= 1) {
newText.write('+');
if (newValue.selection.end >= 1) selectionIndex++;
}
if (newTextLength >= 3) {
newText.write(newValue.text.substring(0, usedSubstringIndex = 2) + ' ');
if (newValue.selection.end >= 2) selectionIndex += 1;
}
// Dump the rest.
if (newTextLength >= usedSubstringIndex)
newText.write(newValue.text.substring(usedSubstringIndex));
return new TextEditingValue(
text: newText.toString(),
selection: new TextSelection.collapsed(offset: selectionIndex),
);
}
}
final _mobileFormatter = NumberTextInputFormatter();
TextFormField(
keyboardType: TextInputType.phone,
maxLength: 15,
inputFormatters: <TextInputFormatter>[
WhitelistingTextInputFormatter.digitsOnly,
_mobileFormatter,
],
decoration: InputDecoration(
icon: Icon(Icons.phone_iphone),
hintText: "Mobile*",
),
)
Solution for RU numbers. We have identical numbers, but written in different ways. 8900.. = +7900.. Also if we start typing with 9, it can automatically become 9.. > +79..
So, this code result will be: +7(900)000-00-00
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class NumberTextInputFormatter extends TextInputFormatter {
@override
TextEditingValue formatEditUpdate(
TextEditingValue oldValue, TextEditingValue newValue) {
final newTextLength = newValue.text.length;
int selectionIndex = newValue.selection.end;
int usedSubstringIndex = 1;
final newTextBuffer = StringBuffer();
if (newTextLength >= 1) {
if (newValue.text.startsWith(RegExp(r'[789]'))) {
newTextBuffer.write('+7');
if (newValue.text.startsWith('9')) {
newTextBuffer.write('(9');
selectionIndex = 4;
}
if (newValue.selection.end >= 1) selectionIndex++;
}
}
if (newTextLength >= 2) {
newTextBuffer
.write('(' + newValue.text.substring(1, usedSubstringIndex = 2));
if (newValue.selection.end >= 2) selectionIndex++;
}
if (newTextLength >= 5) {
newTextBuffer.write(
newValue.text.substring(usedSubstringIndex, usedSubstringIndex = 4) +
')');
if (newValue.selection.end >= 4) selectionIndex++;
}
if (newTextLength >= 8) {
newTextBuffer.write(
newValue.text.substring(usedSubstringIndex, usedSubstringIndex = 7) +
'-');
if (newValue.selection.end >= 7) selectionIndex++;
}
if (newTextLength >= 10) {
newTextBuffer.write(
newValue.text.substring(usedSubstringIndex, usedSubstringIndex = 9) +
'-');
if (newValue.selection.end >= 9) selectionIndex++;
}
// Dump the rest.
if (newTextLength > usedSubstringIndex) newTextBuffer.write(newValue.text.substring(usedSubstringIndex, newTextLength));
return TextEditingValue(
text: newTextBuffer.toString(),
selection: TextSelection.collapsed(offset: selectionIndex),
);
}
}