How to fix the cursor movement with onChange event of flutter? - flutter

The cursor is continuously moving to front while typing data in text field.
Before it is not there but once I wired onChange event, it is happening.
My issue:
My code:
Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(
controller: descriptionController,
decoration: InputDecoration(
labelText: 'Any Details',
hintText: "e.g. Whatever details you want to save",
labelStyle: textStyle,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5.0)
),
),
keyboardType: TextInputType.text,
onChanged: (String string){
setState(() {
if (string != null){
coinOrder.description = string;
}
});
},
),
)

you can use onFieldSubmitted
that will work too
enter image description here

You can use one string variable to store value so this issue will not accrue.
see the below code.
String? details;
Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(
controller: descriptionController,
decoration: InputDecoration(
labelText: 'Any Details',
hintText: "e.g. Whatever details you want to save",
labelStyle: textStyle,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5.0)
),
),
keyboardType: TextInputType.text,
onChanged: (String string){
setState(() {
if (string != null){
//coinOrder.description = string;
details=string;
}
});
},
),
)

Related

Error ocures in onTap property while calling method

TextField(
textAlign: TextAlign.center,
obscureText: _obscureText,
onChanged: (value) {
//Do something with the user input.
password = value;
},
style: const TextStyle(color: Colors.black),
decoration: const InputDecoration(
hintText: 'Enter your Password.',
hintStyle: TextStyle(color: Colors.black26),
suffix: InkWell(
child: Icon(Icons.visibility),
onTap: _togglePasswordView,
//here is error in onTap
),
contentPadding:
EdgeInsets.symmetric(vertical: 10.0, horizontal: 20.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(32.0)),
),
This is all the code of the page, there is erron in onTap function in suffix. the error message shows that //Invalid constant value//
The Image of the error is here ,
decoration: const InputDecoration
You defined input decoration as constant but on error it wont be constant. Remove const

Change the error message position in Flutter

I have to make one application which take so many user input , that's why i use so many Textfiled in my code for taking user input.
An Textfiled validation time I simply use List of Global keys and it's work perfactly.
But problem is when user give wrong input then textfiled show an error message that time my Textbox UI can change (UI well change in very appropriately).
Pleas help , what can i do so my error message postion will be changed.
TextFiled code :
//this is inside the statfull Widget
GlobalKey<FormState> _formkeySubNumber = new GlobalKey();
Widget SubNumber_Input_Box() {
return Form(
//for form validation
key: _formkeySubNumber,
child: Container(
margin: EdgeInsets.only(top: 7, left: 6),
height: 38,
width: 300,
decoration: BoxDecoration(
color: HexColor("#D9D9D9"),
borderRadius: BorderRadius.all(Radius.circular(10)),
),
//padding
child: Padding(
padding: EdgeInsets.only(left: 12),
//textfiled
child: TextFormField(
//for validation
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please Enter Subject Number';
}
return null;
},
//for storing user input && value in string format so we convert into the int formate
onChanged: (value) {
subjectNumber = int.tryParse(value)!;
},
//for only number
keyboardType: TextInputType.number,
decoration: const InputDecoration(
hintText: "Enter Minimum-4 to Maximum-8 Subject",
hintStyle: TextStyle(
fontFamily: "RobotoSlab",
fontSize: 14,
),
//for remove underline from input filed
border: InputBorder.none,
),
//for store only integer value
inputFormatters: <TextInputFormatter>[
FilteringTextInputFormatter.allow(RegExp(r'[0-9]')),
],
),
),
),
);
}
And this call inside the one Button Like that
[Container(
margin: EdgeInsets.only(top: 5),
child: ElevatedButton(
child: Text("Go"),
style: ElevatedButton.styleFrom(
primary: HexColor("#EE6C4D"),
//this colour set (opacity is low) when button is disable
onSurface: HexColor("#E0FBFC"),
),
//store user value -->subjectNumber
onPressed: isGoButtonActive
? () {
//for Form Validation
if (_formkeySubNumber.currentState!
.validate()) {
//this show the container after prerssed button
showContainer1();
}
setState(() {
// //this is for store subjectnumber value from user input
// subjectNumber =
// subNumber_Controller.text;
// print("Subject Number Is : $subjectNumber");
});
}
: null,
),
),]
You have created a container around the textfield with specific height. For styling a textfield you can use
TextField(
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10.0),
),
filled: true,
hintStyle: TextStyle(color: Colors.grey),
hintText: "Type in your text",
fillColor: Colors.white),
)
This way the error message appears below the textfield and outside the white area.
You can remove the height from Form> Container. And it will give you flexible height based on error state.
Widget SubNumber_Input_Box() {
return Form(
key: _formkeySubNumber,
child: Container(
width: 300,
color: HexColor("#D9D9D9"),
//padding
child: Padding(
padding: EdgeInsets.only(left: 12),
child: TextFormField(
autovalidateMode: AutovalidateMode.onUserInteraction, // you might like this as well
Also I will suggest to look at OutlineInputBorder
Widget SubNumber_Input_Box() {
return Form(
key: _formkeySubNumber,
child: Padding(
padding: EdgeInsets.only(left: 12),
child: TextFormField(
autovalidateMode: AutovalidateMode.onUserInteraction,
//for validation
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please Enter Subject Number';
}
return null;
},
//for storing user input && value in string format so we convert into the int formate
onChanged: (value) {
subjectNumber = int.tryParse(value)!;
},
//for only number
keyboardType: TextInputType.number,
decoration: const InputDecoration(
hintText: "Enter Minimum-4 to Maximum-8 Subject",
hintStyle: TextStyle(
fontFamily: "RobotoSlab",
fontSize: 14,
),
enabledBorder: OutlineInputBorder(),
errorBorder: OutlineInputBorder(),
focusedBorder: OutlineInputBorder(),
border: OutlineInputBorder(),
),
//for store only integer value
inputFormatters: <TextInputFormatter>[
FilteringTextInputFormatter.allow(RegExp(r'[0-9]')),
],
),
),
);
}

Flutter Textformfield should be responsive to typing and error

I've often seen where fields are responsive when users are typing, giving realtime feedback. An example is when I'm typing confirm password or email, if the confirm password or email hasn't matched the password while typing it returns error by marking turning the border of the field red until it matches the correct input. I have written this code, how do I improve the code to be responsive as described.
Widget _buildConfirmPasswordTF() {
return Column(crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[
// Text('Password', style: kLabelStyle,),
SizedBox(height: 10.0),
Container(alignment: Alignment.centerLeft, decoration: kBoxDecorationStyle, height: 60.0, child: TextFormField(
validator: ( confirmPassword ){
if ( confirmPassword.trim() != _password.isValidPassword ) {
return null;
} else {
return 'Password doesn\'t match';
}
},
obscureText: true, style: TextStyle(color: Colors.white, fontFamily: 'OpenSans',),
decoration: InputDecoration(border: InputBorder.none, contentPadding: EdgeInsets.only(top: 14.0),
prefixIcon: Icon(Icons.lock, color: Colors.white,),
hintText: 'Enter Confirm Password',
hintStyle: kHintTextStyle,
errorBorder: OutlineInputBorder( borderSide: BorderSide( color: Colors.red ) ),
focusedErrorBorder: OutlineInputBorder( borderSide: BorderSide( color: Colors.red ) )
),
),
),
],
);
}
This is where I set the hintText
final kHintTextStyle = TextStyle(
color: Colors.white54,
fontFamily: 'OpenSans',
);
This is where I set the labelStyle
final kLabelStyle = TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontFamily: 'OpenSans',
);
This is where I set the border decoration
final kBoxDecorationStyle = BoxDecoration(
color: Color(0xFF6CA8F1),
borderRadius: BorderRadius.circular(10.0),
boxShadow: [
BoxShadow(
color: Colors.black12,
blurRadius: 6.0,
offset: Offset(0, 2),
),
],
);
you need autovalidateMode: AutovalidateMode.onUserInteraction, pass this in textformfield.
You can do that with a Form() providing it a key and a autoValidateMode to make sure the fields have value or that the value is something you except, you can add another field to confirm the passwork or email and compare the value of the field in the onChanged with the value of the other email field to make sure they match.
import 'package:email_validator/email_validator.dart';
final formKey = GlobalKey<FormState>();
final _emailController = TextEditingController();
final _passwordController = TextEditingController();
bool isValid = false;
_emailController.addListener(
() {
//With this, you can "listen" all the changes on your text while
//you are typing on input
//use setState to rebuild the widget
if (EmailValidator.validate(_emailController.text)) {
setState(() {
isValid = true;
});
} else {
setState(() {
isValid = false;
});
}
},
);
Form(
key: formKey,
autovalidateMode: AutovalidateMode.onUserInteraction,
child: Column(
children: [
Padding(
padding: EdgeInsets.symmetric(
horizontal: size.width * 0.105),
child: TextFormField(
validator: (value) =>
!EmailValidator.validate(value)
? 'Enter a valid email'
: null,
keyboardType: TextInputType.emailAddress,
textAlign: TextAlign.center,
controller: _emailController,
decoration: kInputDecoration.copyWith(
hintText: 'Enter your email'),
),
),
SizedBox(
height: 18,
),
Padding(
padding: EdgeInsets.symmetric(
horizontal: size.width * 0.105),
child: TextFormField(
obscureText: true,
validator: (value) =>
value.isEmpty ? 'Enter your password' : null,
keyboardType: TextInputType.text,
textAlign: TextAlign.center,
controller: _passwordController,
decoration: kInputDecoration.copyWith(
hintText: 'Enter your password'),
),
),
],
),
),

Horizontal scroll in TextFormField flutter on text input

I have an email input text field when I write more text than the width of this input, the rest of the text is not visible. Is there a way to have a horizontal scroll as I input into this text form field?
The following image describes the behavior I want.
Edit: My Code
Container(
width: 270,
height: 42,
child: new TextFormField(
validator: (val) => val.isEmpty ? 'Enter an email' : null,
decoration: new InputDecoration(
icon: Icon(
Icons.email_outlined,
),
labelText: 'Email',
border: new OutlineInputBorder(
borderRadius: new BorderRadius.circular(25.0),
borderSide: new BorderSide(),
),
),
keyboardType: TextInputType.emailAddress,
onChanged: (val) {
setState(() => email = val);
},
),
),
This is what happens when I type beyond the width of the TextFormField
There are two ways to go about this:
You can add the isDense property to your TextFormField, in which case your code will look like this:
Container(
width: 270,
height: 42,
child: TextFormField(
textAlignVertical: TextAlignVertical.center,
validator: (val) => val!.isEmpty ? 'Enter an email' : null,
decoration: new InputDecoration(
isDense: true,
icon: Icon(
Icons.email_outlined,
),
labelText: 'Email',
border: new OutlineInputBorder(
borderRadius: new BorderRadius.circular(25.0),
borderSide: new BorderSide(),
),
),
keyboardType: TextInputType.emailAddress,
onChanged: (val) {
setState(() => email = val);
},
),
),
This fixes the problem to an extent, however if font that extends lower(like commas, semicolons etc. still get clipped off). The next method fixes this:
Use the contentPadding property, since if you check the source code, all isDense does is modify the contentPadding property's value. This is some of the actual code behind isDense:
if (decoration!.filled == true) { // filled == null same as filled == false
contentPadding = decorationContentPadding ?? (decorationIsDense
? const EdgeInsets.fromLTRB(12.0, 8.0, 12.0, 8.0)
: const EdgeInsets.fromLTRB(12.0, 12.0, 12.0, 12.0));
} else {
// Not left or right padding for underline borders that aren't filled
// is a small concession to backwards compatibility. This eliminates
// the most noticeable layout change introduced by #13734.
contentPadding = decorationContentPadding ?? (decorationIsDense
? const EdgeInsets.fromLTRB(0.0, 8.0, 0.0, 8.0)
: const EdgeInsets.fromLTRB(0.0, 12.0, 0.0, 12.0));
}
As you can see, all Flutter does behind the scenes is assign hardcoded values to your arguments based on the parameters you've passed. In your case, the best configuration seems to be:
Container(
width: 270,
height: 42,
child: TextFormField(
textAlignVertical: TextAlignVertical.center,
validator: (val) => val!.isEmpty ? 'Enter an email' : null,
decoration: InputDecoration(
contentPadding: EdgeInsets.fromLTRB(12.0, 8.0, 12.0, 8.0),
icon: Icon(
Icons.email_outlined,
),
labelText: 'Email',
border: new OutlineInputBorder(
borderRadius: new BorderRadius.circular(25.0),
borderSide: new BorderSide(),
),
),
keyboardType: TextInputType.emailAddress,
onChanged: (val) {
setState(() => email = val);
},
),
),
The above code fixes your issue, but might create more problems if your font height changes.

How can i change the focus to other textfield after i complete max characters in Flutter?

How do I change the focus to other node after completion max characters without pressing next/done in Flutter ?. How do I pass the control to other TextField using Focus node. I want to pass the control to next textfield after 4 characters of every textfield.
Widget serailKey1() {
return TextField(
controller: controller_key1,
focusNode: _serialKeyFN1,
textAlign: TextAlign.center,
keyboardType: TextInputType.text,
textCapitalization: TextCapitalization.characters,
style: textStyle,
maxLength: 4,
decoration: new InputDecoration(
counterText: "",
border: new OutlineInputBorder(
borderRadius: const BorderRadius.all(
const Radius.circular(0.0),
),
),
),
onEditingComplete: ()=> FocusScope.of(context).requestFocus(_serialKeyFN2),
);
}
Widget serailKey2() {
return TextField(
controller: controller_key2,
focusNode: _serialKeyFN2,
textAlign: TextAlign.center,
keyboardType: TextInputType.text,
style: textStyle,
textCapitalization: TextCapitalization.characters,
maxLength: 4,
decoration: new InputDecoration(
counterText: "",
border: new OutlineInputBorder(
borderRadius: const BorderRadius.all(
const Radius.circular(0.0),
),
),
),
onEditingComplete: ()=> FocusScope.of(context).requestFocus(_serialKeyFN3),
);
}
This works fine for me:
FocusNode fNode = FocusNode();
...
TextField(onChanged: (value){
if(value.length == 4)
FocusScope.of(context).requestFocus(fNode);
}),
TextField(focusNode: fNode),