TextFormField onChanged is not getting called when no character Flutter - flutter

I have 1 functionality of adding TextFormField in Container on Button press upto 4 TextFormField like below image and when there's no text in TextFormField i want to remove that TextFormField so i have put that login in onChange.
When i press the button 1s time and it will add TextFormField and without typing any character if i press delete button from keyboard onChange is not getting called.
Please see this video: https://drive.google.com/file/d/1Yln48d5JHvvYdb4LRDXxmlzPzlC__xYq/view?usp=sharing
Here is my code.
TextFormField(
controller: bullet2Controller,
focusNode: focusNode2,
maxLines: null,
minLines: 1,
textCapitalization:TextCapitalization.sentences,
cursorColor: Colors.black,
showCursor: true,
autofocus: true,
textAlign: TextAlign.start,
inputFormatters: [LengthLimitingTextInputFormatter(140),],
onChanged: (value) {
setState(() {
if (value.isEmpty) {
isBullet2Visible = false;
if (isBullet1Visible) {
focusNode1.requestFocus();
} else if (isBullet3Visible) {
focusNode3.requestFocus();
} else if (isBullet4Visible) {
focusNode4.requestFocus();
} else {
FocusScope.of(context).unfocus();
}
if (_counter > 0) {
_counter--;
}
}
if (kDebugMode) {
print("${value.length.toString()} character(s)");
}
});
},
decoration: const InputDecoration(disabledBorder:
InputBorder.none,
border:
InputBorder.none,
filled: true,
fillColor: Colors.white,
),
keyboardType:
TextInputType
.multiline,
textInputAction:
TextInputAction.done,
),
Is it default behaviour or do i need to do any extra step to make it work.

this is a default behaviour.
when your value = '' and you press delete it is still equal to '' and onChanged not getting called.
to achieve your goals you should use a listener like RawKeyboardListener

Thanks to Vladyslav Ulianytskyi suggestion.
I have done this with the use of RawKEyboardListner. Here is the sample code.
RawKeyboardListener(
autofocus: true,
onKey: (event) {
setState(() {
if (event.isKeyPressed(LogicalKeyboardKey.backspace)) {
print("Perform Your Action");
}
});
},
focusNode: FocusNode(),
child: TextFormField(controller: bullet2Controller,
focusNode: focusNode2,
maxLines: null,
minLines: 1,
textCapitalization: TextCapitalization.sentences,
cursorColor: Colors.black,
showCursor: true,
autofocus: true,
textAlign: TextAlign.start,
inputFormatters: [LengthLimitingTextInputFormatter(140),
],
decoration: const InputDecoration(
disabledBorder: InputBorder.none,
border: InputBorder.none,
filled: true,
fillColor: Colors.white,
),
keyboardType: TextInputType.multiline,
textInputAction: TextInputAction.done,
),
),
)

You can try it will below code hope it's work for you
TextEditingController bullet2Controller = TextEditingController();
int currentTextLength = 0;
TextFormField(
maxLines: null,
controller: bullet2Controller,
decoration: InputDecoration(
hintText: 'Type your observations'
),
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w300,
fontFamily: 'Roboto'
),
onChanged: (String newText){
if (newText != ''){
if(newText[0] != '•'){
newText = '• ' + newText;
bullet2Controller.text = newText;
bullet2Controller.selection = TextSelection.fromPosition(TextPosition(offset: bullet2Controller.text.length));
}
if(newText[newText.length - 1] == '\n' && newText.length > currentTextLength){
bullet2Controller.text = newText + '• ';
bullet2Controller.selection = TextSelection.fromPosition(TextPosition(offset: bullet2Controller.text.length));
}
currentTextLength = bullet2Controller.text.length;
}
}
)
let me know if it's work for you or let me know if there any question.

Related

how to use two type MakedInputFormatter for phonenumber in flutter?

I want to get two type Inputformatter, 000-000-0000 or 000-0000-0000 for phoneNumber.
I use flutter_multi_formatter. below code just allow put 000-000-0000.
I want inputformatter to make 000-000-0000 if the input length is 12.
I want inputformatter to maek 000-0000-0000 if the input length is 13.
Widget _phoneNumberFormField() {
return Expanded(
child: TextFormField(
focusNode: _telephoneFocusNode,
enabled: _verificationStatus == _VerificationStatus.none ? true : false,
autovalidateMode: AutovalidateMode.onUserInteraction,
style: Theme.of(context)
.textTheme
.titleMedium!
.copyWith(fontSize: 16.0.sp),
controller: _phoneNumberEditingController,
onChanged: (data) {
_areAllTheFormsFilledAndValid();
},
validator: (phoneNumber) {
if (phoneNumber!.length >= 12) {
String pattern = r'(^01([0|1|6|7|8|9])-?([0-9]{3,4})-?([0-9]{4})$)';
RegExp regExp = RegExp(pattern);
if (regExp.hasMatch(phoneNumber)) {
return null;
} else {
return 'check phonenumber.';
}
}
return null;
},
textAlign: TextAlign.center,
keyboardType: TextInputType.phone,
inputFormatters: [
MaskedInputFormatter("000-0000-0000"),
MaskedInputFormatter("000-000-0000"),
],
decoration: InputDecoration(
contentPadding: EdgeInsets.zero,
hintText: "put phonenumber.",
hintStyle: TextStyle(
fontSize: 16.0.sp, color: Theme.of(context).hintColor),
border: _outlineInputBorder()),
),
);
}
I found way.
inputFormatters: [
_phoneNumberEditingController.text.length == 12
? MaskedInputFormatter("000-0000-0000")
: MaskedInputFormatter("000-000-00000")
],

how to limit the user to enter number outside the given range(says 1 to 4000) in flutter textformfield

Restricts the user's input.
For example, if I set the numeric limit to 4000, the user cannot enter a number greater than 4000.
TextFormField(
//TODO:보유수량 이상 쓰는것 방지할것.
controller: _recruitStockEditingController,
keyboardType: TextInputType.number,
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
decoration: InputDecoration(
contentPadding: EdgeInsets.only(
left: 21.0.w, top: 11.0.h, bottom: 11.0.h),
hintText: "수량을 입력해주세요.",
hintStyle: TextStyle(
fontSize: 14.0.sp, color: const Color(0xff696C75)),
border: OutlineInputBorder(
borderSide: const BorderSide(color: Color(0xffCACBD4)),
borderRadius: BorderRadius.circular(6))),
),
Try this with TextInputFormatter
import 'package:flutter/services.dart';
class NumberLimitFormatter extends TextInputFormatter {
#override
TextEditingValue formatEditUpdate(TextEditingValue oldValue, TextEditingValue newValue) {
if(newValue.text == "") return newValue;
if(int.parse(newValue.text.toString())<4000){
return newValue;
}
return oldValue;
}
}
Uasge:
TextField(
controller: myController,
keyboardType: TextInputType.number,
inputFormatters: [
NumberLimitFormatter(),
FilteringTextInputFormatter.digitsOnly,
],
),
Using Validator and TextFormField:
TextFormField(
keyboardType: TextInputType.number,
autovalidateMode: AutovalidateMode
.onUserInteraction, // to instantly valid the input
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
],
validator: (String? value) {
if (value == null || value.isEmpty)
return "Enter number";
else if (int.parse(value) > 4000)
return "Entered number can't be greater than 4000";
else
return null;
}),
try using a validator.
validator: (value) {
if (value > 4000) {
return "You can't enter a value greater than 4000";
}
return null;
},

Dynamically change keyboard type - Flutter

I need to change the keyboard dynamically. the keyboard starts in TextInputType.text, when the user types 3 letters it is switched to TextInputType.number and the user types 4 numbers. ex: ABC1234.
final _controller = TextEditingController();
TextFormField(
decoration: InputDecoration(
labelText: "code",
hintText: 'ABC1234'),
controller: _myController,
keyboardType: TextInputType.text,
),
To change your TextInputType dynamically, what you can do is:
final _controller = TextEditingController();
//Creating a variable to store the type and initializing it with the default text type.
var keyboardType = TextInputType.text;
TextFormField(
decoration: InputDecoration(
labelText: "code",
hintText: 'ABC1234'),
controller: _myController,
//Passing the variable created in here
keyboardType: keyboardType,
onChanged: (value) {
//Checking if the value's length is less than 4, if it is, it should be type `text`.
if(value.isEmpty || value.length < 4) {
setState(() => keyboardType = TextInputType.text);
} else {
//Else, it should be type `number`
setState(() => keyboardType = TextInputType.number);
}
}
),
The will change the keyboard type dynamically but it may not change the keyboard, and you may have to close and open the keyboard again.
You can use keyboardType like this. It will be for both numbers and letters.
keyboardType: TextInputType.visiblePassword
Here is your working code
The keyboard is also changed automatically
final _controller = TextEditingController();
late FocusNode myFocusNode = FocusNode();
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: Center(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: TextFormField(
style: Theme.of(context).textTheme.bodyText2,
controller: _controller,
focusNode: myFocusNode,
textCapitalization: TextCapitalization.characters,
keyboardType: (_controller.text.length >= 3) ? TextInputType.number : TextInputType.name,
onChanged: (text) {
if (_controller.text != text.toUpperCase()) {
_controller.value = _controller.value.copyWith(text: text.toUpperCase());
}
if (_controller.text.length == 3){
setState(() {
myFocusNode.unfocus();
Future.delayed(const Duration(milliseconds: 50)).then((value) {
myFocusNode.requestFocus();
});
});
}
},
inputFormatters: [
FilteringTextInputFormatter.allow(
RegExp('[a-zA-Z0-9]'))
],
decoration: const InputDecoration(labelText: 'ABC1234')),
),
),
);
}
Output:
Declare a variable like your controller for keyboardtype, where keyboardtype is variable and TextInputTupe is it's datatype.
TextInputType keyboardtype = TextInputType.text;
now, check yout textformfield's String, If your string.length is greater than 3 then keyboard type is TextInputType.number
check the length into onchanged in textformfield
final _controller = TextEditingController();
TextInputType keyboardType = TextInputType.text;
TextFormField(
decoration: InputDecoration(
labelText: "code",
hintText: 'ABC1234'),
controller: _myController,
keyboardType: TextInputType.text,
onChanged: (value){
var inputText = _myController.text;
if(inputText.length>3){
keyBoardType = TextInputType.number;
}
}
),
It would be better if you use some regex to check your inputformat into the inputFormatters in your textformfield. if you don't know about inputformatters just google it.

flutter- TextFiled suffix Icon was not working when voice over is switched ON

In my application We have a Close icon at the end of the Textfield.
closeIcon was added in textField's suffix icon. So it is not read out by the voice over and not functioning as expected. (Overriding by textfield's semantic widget) Without voiceOver it is working fine. We have added this closeIcon to textfield SuffixIcon. (It must be like this). Anyone please help me how closeIcon will work with voiceOver.
code:
child:
TextField(
key: widget.inputKey,
textInputAction: widget.textInputAction,
onEditingComplete: widget.onEditCompleted,
style: style.inputStyle.textStyle,
decoration: InputDecoration(
isDense: true,
hintText: widget.hint,
errorStyle: style.errorStyle.textStyle,
hintStyle: style.hintStyle.textStyle,
prefixStyle: style.prefixStyle.textStyle,
suffixStyle: style.suffixStyle.textStyle,
counterStyle: style.counterStyle.textStyle,
suffixIconConstraints: context.theme.getIconStyle(formInputPrefixIconStyleId).constraints,
suffixIcon: _suffixIcon(context),
prefixIconConstraints: const BoxConstraints(minWidth: 8, minHeight: 8),
prefixIcon: widget.textFieldPrefix != null ? _fieldPrefix(style) : null,
border: _getBorderStyle(style),
focusedBorder: _getFocusedBorderStyle(style),
enabledBorder: _getEnabledBorderStyle(style),
),
onChanged: (text) {
setState(() {
_shouldShowClearIcon = text.isNotEmpty;
});
widget.onChanged.call(text);
},
focusNode: widget.focusNode,
controller: widget.controller,
showCursor: true,
keyboardAppearance: style.keyboardAppearance,
),
),
),
Visibility(
visible: _hasError(),
child: AppFieldError(
key: const Key('bottomErrorContainer'),
errorText: widget.alertMessage,
style: context.theme
.getContainerStyle(widget.showWarning ? formWarningContainerStyleId : formErrorContainerStyleId),
),
),
],
),
));
}
Widget _suffixIcon(BuildContext context) {
if (widget.hasShowSuccess) {
return _successIcon(context);
}
if (_shouldShowClearIcon && widget.isEnabled) {
return _clearIcon(context);
}
return null;
}

Custom money TextField in Flutter

I just started learning Flutter and i am trying to figure out how the user can enter an amount in a TextField ,for example 1234567 , should look like this when user is typing :
1.00
12.00
123.00
1 234.00
12 345.00
123 456.00
1 234 567.00
I tried using this library : mask_text_input_formatter, but i can't figure out how to do it. Here is my code
var maskFormatter = new MaskTextInputFormatter(
mask: '### ### ###.00', filter: {"#": RegExp(r'[0-9]')});
TextFormField(
keyboardType: TextInputType.number,
inputFormatters: [maskFormatter],
onChanged: (value) {},
decoration: InputDecoration(
prefixIcon: Icon(Icons.monetization_on),
hintText: 'Amount',
border: OutlineInputBorder(),
),
validator: (value) {
if (value.isEmpty) {
return 'Please enter some text';
}
return null;
},
),
Any idea on how to achieve that result.
Declare and initialize a text controller and assign it to the text field. Update its value on change in input!
TextEditingController _moneyController = TextEditingController();
#override
void initState() {
super.initState();
_moneyController.text = '.00';
}
TextFormField(
keyboardType: TextInputType.number,
inputFormatters: [maskFormatter],
onChanged: (value) {},
decoration: InputDecoration(
prefixIcon: Icon(Icons.monetization_on),
hintText: 'Amount',
border: OutlineInputBorder(),
),
validator: (value) {
if (value.isEmpty) {
return 'Please enter some text';
}
return null;
},
//added code here
controller: _moneyController,
),