split text in textformfield with a character in flutter - flutter

perhaps someone has encountered such a problem, I need to configure textformfield so that the text is entered in the form in the format / so that the user does not have to type / himself, it seems like you need to use inputformatter, but I can't figure out how to do it

maskformatter.dart
class MaskedTextInputFormatter extends TextInputFormatter {
final String? mask;
final String? separator;
MaskedTextInputFormatter({
#required this.mask,
#required this.separator,
}) {
assert(mask != null);
assert(separator != null);
}
#override
TextEditingValue formatEditUpdate(
TextEditingValue oldValue, TextEditingValue newValue) {
if (newValue.text.isNotEmpty) {
if (newValue.text.length > oldValue.text.length) {
if (newValue.text.length > mask!.length) return oldValue;
if (newValue.text.length < mask!.length &&
mask![newValue.text.length - 1] == separator) {
return TextEditingValue(
text:
'${oldValue.text}$separator${newValue.text.substring(newValue.text.length - 1)}',
selection: TextSelection.collapsed(
offset: newValue.selection.end + 1,
),
);
}
}
}
return newValue;
}
in textfield use :-
inputFormatter: [
MaskedTextInputFormatter(
mask: '****-****-****-****',
separator: '-',
),
]

I think you are looking for mask text. Try this package mask_text
var maskFormatter = new MaskTextInputFormatter(
mask: '+# (###) ###-##-##',
filter: { "#": RegExp(r'[0-9]') },
type: MaskAutoCompletionType.lazy
);
And assign it to the textfield
TextField(inputFormatters: [maskFormatter])

Related

About securing password field in textformfield in flutter

I want to hide completely the password field, I set obscure text true but it shows the characters as I type them how hide completely the characters?
If you want completely hide it, you must use controller and implement like this:
class TextFieldPassWord extends StatefulWidget {
#override
_TextFieldPassWordState createState() => _TextFieldPassWordState();
}
class _TextFieldPassWordState extends State<TextFieldPassWord> {
String _valueShow = "";
String _value = "";
#override
Widget build(BuildContext context) {
return Scaffold(
body: TextField(
controller: TextEditingController.fromValue(
TextEditingValue(
text: _valueShow,
selection: TextSelection.collapsed(offset: _valueShow.length),
),
),
onChanged: (String str) {
String value = "";
if (str.length > _value.length) {
value += str.substring(_value.length, str.length);
}
if (str.length < _value.length) {
value = _value.substring(1, str.length);
}
String valueToShow = "*" * str.length;
setState(() {
_valueShow = valueToShow;
_value = value;
});
},
),
);
}
}

Flutter Text Field allow user to insertion of a number within a given range only

I would to force the insertion of only values between 1-20. if user enter 2 it's okay but if user enter 1 after 2 (21) then Text Field will not allow to enter 1 after 2. Is there any RegExp for it.
I tried like this but it's only allow for numbers
inputFormatters: [FilteringTextInputFormatter.allow(RegExp('[1-9,.,:]'))],
Try below code hope its help to you. in below code if you put more than 20 value the cursor takes the first position.
Create one class and declare it minimum and maximum value.
class LimitRange extends TextInputFormatter {
LimitRange(
this.minRange,
this.maxRange,
) : assert(
minRange < maxRange,
);
final int minRange;
final int maxRange;
#override
TextEditingValue formatEditUpdate(
TextEditingValue oldValue, TextEditingValue newValue) {
var value = int.parse(newValue.text);
if (value < minRange) {
print('value print in between 1 - 20');
return TextEditingValue(text: minRange.toString());
} else if (value > maxRange) {
print('not more 20');
return TextEditingValue(text: maxRange.toString());
}
return newValue;
}
}
Your Widget:
TextField(
keyboardType: TextInputType.number,
inputFormatters: [
LengthLimitingTextInputFormatter(2),
LimitRange(1, 20),
],
),

How to implement a text mask in Flutter

As described in the title, how to implement text mask in Flutter.
I am just writing a one below but not that suitable, since it can't display the mask to the user when typing, for example, when the text mask is 'MM/HH', if we do not display the slash during the user's typing, the user will typing the slash '/' themself, as they do not know the slash will auto-fill the input. There is a example here that can explain what am I said (It's a web implementation, not Flutter), so how to implement the mask-like in this link in Flutter?
This is my current implementation.
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class MaskedTextInputFormatter extends TextInputFormatter {
final String mask;
final String separator;
MaskedTextInputFormatter({
#required this.mask,
#required this.separator,
}) {
assert(mask != null);
assert(separator != null);
}
#override
TextEditingValue formatEditUpdate(
TextEditingValue oldValue, TextEditingValue newValue) {
if (newValue.text.length > 0) {
if (newValue.text.length > oldValue.text.length) {
if (newValue.text.length > mask.length) return oldValue;
if (newValue.text.length < mask.length &&
mask[newValue.text.length - 1] == separator) {
return TextEditingValue(
text:
'${oldValue.text}$separator${newValue.text.substring(newValue.text.length - 1)}',
selection: TextSelection.collapsed(
offset: newValue.selection.end + 1,
),
);
}
}
}
return newValue;
}
}
Any help are appreciated!
PS: I searched a Flutter package mask_text_input_formatter, seems it also can't display the mask when typing, see issue.
try by adding extra condition for modifying text value
add 1 extra condition.
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class MaskedTextInputFormatter extends TextInputFormatter {
final String mask;
final String separator;
MaskedTextInputFormatter({
#required this.mask,
#required this.separator,
}) {
assert(mask != null);
assert(separator != null);
}
#override
TextEditingValue formatEditUpdate(
TextEditingValue oldValue, TextEditingValue newValue) {
if (newValue.text.length > 0) {
if (newValue.text.length > oldValue.text.length) {
if (newValue.text.length > mask.length) return oldValue;
if (newValue.text.length < mask.length &&
mask[newValue.text.length - 1] == separator &&
newValue.text.substring(newValue.text.length - 1) != separator) {
return TextEditingValue(
text:
'${oldValue.text}$separator${newValue.text.substring(newValue.text.length - 1)}',
selection: TextSelection.collapsed(
offset: newValue.selection.end + 1,
),
);
}
}
}
return newValue;
}
}
by using regex depending your need.
FilteringTextInputFormatter(r"[A-za-z][A-Za-z]\/[A-za-z][A-Za-z]", allow: false);
OR
FilteringTextInputFormatter(r"[A-za-z0-9][A-Za-z0-9]\/[A-za-z0-9][A-Za-z0-9]", allow: false);
example as below
allow parameter is for if you want to allow particular pattern to be accepted or not
Textfield(
label: "CardNumber",
hint: "CardNumber",
focusNode: cardNumberFocus,
textInputFormatter: [
MaskedTextInputFormatter(mask: 'xxxx xxxx xxxx xxxx', separator: ' '),
FilteringTextInputFormatter(r"[A-za-z0-9][A-Za-z0-9]\/[A-za-z0-9][A-Za-z0-9]", allow: true);
],
);

Flutter: TextFiled become clear when add new number

In my application i have a text field.I create a TextInputFormatter to add as a inputFormatters to my TextField:
class CurrencyTextInputFormatter extends TextInputFormatter {
#override
TextEditingValue formatEditUpdate(
TextEditingValue oldValue, TextEditingValue newValue) {
if (newValue.text.isEmpty) {
return newValue.copyWith(text: '');
} else if (newValue.text.compareTo(oldValue.text) != 0) {
var selectionIndexFromTheRight =
newValue.text.length - newValue.selection.end;
final f =
NumberFormat.currency(locale: 'en', decimalDigits: 0, symbol: '');
var num = int.parse(newValue.text.replaceAll(RegExp('[^0-9]'), ''));
final newString = f.format(num).trim();
return TextEditingValue(
text: newString,
selection: TextSelection.collapsed(
offset: newString.length - selectionIndexFromTheRight),
);
} else {
return newValue;
}
}
}
everything is ok and when i add a price in TextField, the price is separated with , from right to left.
TextField(
textAlignVertical: TextAlignVertical.center,
controller: amountController,
inputFormatters: [
CurrencyTextInputFormatter(),
LengthLimitingTextInputFormatter(15),
],
In the parent of TextField in initState i initialized text field controller :
#override
void initState() {
super.initState();
amountController.text =
commaFormatter.format(widget.provider.totalUnpaidAmount);
}
commaFormatter use NumberFormat from intl to add comma between numbers:
final commaFormatter = NumberFormat("#,###");
The problem is here:
When number added to textfield by it's controller, when i want to delete this number by softkeyboard delete key, the number is not deleted ?But when i add a a new number, the old number completely deleted !!!!
How can i fix this problem?
I want to when number is added to this textfiled, Be editable !!!

Is there a way for InputFormatters on a TextFormField to be executed when the form is initially displayed?

When inputFormatters are specified on a TextFormField, the initialValue is not processed by the inputFormatters.
This seems odd. Is there a recommended way to get the inputFormatters to format the initialValue.
For example, I have a 5 digit number (i.e. 12345) that should be displayed with a comma separator (12,345) in the input field. By default it displays as 12345, but as soon as I edit the value, the comma separator appears. The comma separator should be displayed on the initial value.
You can create a static method to validate your initialValue
class MyFormater extends TextInputFormatter {
static String defaultFormat(String text) {
// Do whatever you want
return text;
}
#override
TextEditingValue formatEditUpdate(TextEditingValue oldValue, TextEditingValue newValue) {
// Your validations/formats
return null;
}
}
and then you can use it as so
TextFormField(
initialValue: MyFormater.defaultFormat(someString),
inputFormatters: [MyFormater()],
)
I doubt there is other way that will trigger the TextInputFormatter before it has any focus. That initialValue is mean to be already validated and work as a placeholder.
you can use this to set the text directly to the controller without interacting with the text field
var textEditingController = TextEditingController();
textEditingController.value = myFormatter.formatEditUpdate(TextEditingValue(text: ''), TextEditingValue(text: 'my initial value'));
you can set custom inputFormatters in TextField.
for that you must define your filter, for example a function that take String and return a neat( or filtered ) String.
in my case function neatCost() get a string and separate 3 by 3 chars by "," for example take "12345" and return "12,345".
for creating custom inputFormatters :
class NeatCostFilterFormatter extends TextInputFormatter {
#override
TextEditingValue formatEditUpdate(TextEditingValue oldValue, TextEditingValue newValue) {
final StringBuffer newText = StringBuffer();
newText.write(neatCost(newValue.text.replaceAll(",", "")));
print(newValue.text);
print(neatCost(newValue.text.replaceAll(",", "")).length);
return TextEditingValue(
text: newText.toString(),
selection: TextSelection.collapsed(offset: neatCost(newValue.text.replaceAll(",", "")).length),
);
}
}
and the function:
String neatCost(String cost) {
String res=cost;
if(cost!=null) {
for (int i = 3; i < res.length; i += 4) {
res = res.replaceRange(res.length - i, res.length - i, ",");
}
return res;
}else{
return "";
}
}
after that yo can set your custom formatter to the TextField just like this:
new TextField(
inputFormatters: <TextInputFormatter>[new NeatCostFilterFormatter()]
)