Flutter textfield how to position floating label and error label - flutter

I have a flutter design
when user selects textfield should fill with blue color then floating label padding above the border and textfield content padding should change.
When the textfield has an error both floating label and error label change the color and I have to position them.
Can someone help me how to achieve this as Reusable TextField
Please refer to the image.
Image with Animation

Rather then using label text I would consider using Text() above your TextFormField(). You can try this code below to get your result
FocusNode _focus = FocusNode();
bool _isValidate = true;
GlobalKey<FormState> _key = GlobalKey();
#override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: EdgeInsets.all(15),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: EdgeInsets.only(bottom: 5, left: 11),
child: Text("Field Value",
style: TextStyle(
color:
_focus.hasFocus ? Colors.blue : Colors.white))),
TextFormField(
focusNode: _focus,
onTap: () {
FocusScope.of(context).requestFocus();
},
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(50)),
filled: true,
fillColor:
_focus.hasFocus ? Colors.blue : Colors.transparent),
),
Divider(),
Padding(
padding: EdgeInsets.only(bottom: 5, left: 11),
child: Text("Field Value",
style: TextStyle(
color: _isValidate ? Colors.white : Colors.red))),
Form(
key: _key,
child: TextFormField(
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(50)),
errorStyle:
TextStyle(fontSize: 14, fontWeight: FontWeight.w400)),
validator: (val) {
if (val!.length >= 5) {
setState(() {
_isValidate = false;
});
return "Field Value";
} else {
setState(() {
_isValidate = true;
});
return null;
}
},
),
),
Divider(),
ElevatedButton(
onPressed: () {
final form = _key.currentState;
form!.validate();
},
child: Text("Submit"))
],
)),
);
}

Related

Why isn't the snackbar displaying when the textfields are unfilled in Flutter?

I tested and tried leaving some textfields unfilled. But they aren't displaying any sort of error especially from the snackbar. Can't seem to figure out the issue. I tried changing it up a bit and went off the snackbar documentation as well (https://pub.dev/packages/awesome_snackbar_content/install). But still can't figure out the issue. I'd appreciate any help or hint. Here is the code snippet:
class _SignUpPageState extends State<SignUpPage> {
// Focus nodes for email, password, and retyping passwords
final FocusNode emailFocus = FocusNode();
final FocusNode passwordFocus = FocusNode();
final FocusNode retypePasswordFocus = FocusNode();
// Bool values for obscuring text
bool _obscureTextPassword = true;
bool _obscureTextConfirmPassword = true;
// Manages the state of the form
final _formKey = G
lobalKey<FormState>();
// Refers to the name of the TextEditingController class
TextEditingController _emailController = new TextEditingController();
TextEditingController _passwordController = new TextEditingController();
TextEditingController _retypePasswordController = new TextEditingController();
#override
void dispose() {
// Clean up the controller when the widget is disposed.
emailFocus.dispose();
passwordFocus.dispose();
retypePasswordFocus.dispose();
super.dispose();
}
// Initializing these TextEditingController objects
#override
void initState() {
super.initState();
_emailController = TextEditingController();
_passwordController = TextEditingController();
_retypePasswordController = TextEditingController();
}
void _toggleSignUp() {
setState(() {
_obscureTextPassword = !_obscureTextPassword;
});
}
void _toggleSignUpConfirm() {
setState(() {
_obscureTextConfirmPassword = !_obscureTextConfirmPassword;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Form(
key: _formKey,
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
Color.fromRGBO(73, 77, 235, 1.0),
Color.fromRGBO(75, 0, 130, 0.8)
]),
),
child: Padding(
padding: const EdgeInsets.all(10.0),
child: ListView(
children: [
SizedBox(height: 60,),
Center(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text("Sign Up",
style: TextStyle(fontSize: 20, decoration: TextDecoration.none, color: Colors.white),),
),
),
SizedBox(height: 40,),
Column(
children: [
Container(
height: 45,
width: 350,
padding: EdgeInsets.fromLTRB(30, 0, 30, 0),
child: TextFormField(
keyboardType: TextInputType.emailAddress,
focusNode: emailFocus,
autofocus: true,
textInputAction: TextInputAction.next,
decoration: InputDecoration(
hintText: "Enter Your Email Address",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10.0),
),
contentPadding: EdgeInsets.all(30),
),
controller: _emailController,
validator: (String? value) {
if (value == null || value.isEmpty) {
return "Please enter some text";
}
return null;
},
),
),
SizedBox(height: 40,),
Container(
height: 45,
width: 350,
padding: EdgeInsets.fromLTRB(30, 0, 30, 0),
child: TextFormField(
keyboardType: TextInputType.visiblePassword,
focusNode: passwordFocus,
obscureText: _obscureTextPassword,
textInputAction: TextInputAction.next,
decoration: InputDecoration(
hintText: "Password",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10.0),
),
contentPadding: EdgeInsets.all(30),
),
controller: _passwordController,
),
),
SizedBox(height: 40,),
Container(
height: 45,
width: 350,
padding: EdgeInsets.fromLTRB(30, 0, 30, 0),
child: TextFormField(
keyboardType: TextInputType.visiblePassword,
obscureText: _obscureTextConfirmPassword,
textInputAction: TextInputAction.done,
decoration: InputDecoration(
hintText: "Retype Password",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10.0),
),
contentPadding: EdgeInsets.all(30),
),
controller: _retypePasswordController,
),
),
],
),
SizedBox(
height: 60,
),
ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.black,
padding:
const EdgeInsets.symmetric(horizontal: 110, vertical: 25),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20))),
child: const Text(
'Next',
style: TextStyle(fontSize: 12),
),
onPressed: () {
if (_formKey.currentState!.validate()) {
final snackBar = SnackBar(
/// need to set following properties for best effect of awesome_snackbar_content
elevation: 5,
behavior: SnackBarBehavior.floating,
backgroundColor: Colors.transparent,
content: AwesomeSnackbarContent(
title: 'On Snap!',
message:
'This is an example error message that will be shown in the body of snackbar!',
/// change contentType to ContentType.success, ContentType.warning or ContentType.help for variants
contentType: ContentType.failure,
),
);
} else {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const TabNav()),
);
}
},
),
],
),
),
),
),
);
}
}
The problem is that you are creating the SnackBar but you are not calling it. As you can see at the library's example, you are missing below call :
ScaffoldMessenger.of(context)
..hideCurrentSnackBar()
..showSnackBar(snackBar);

I want to implement OTP verification screen without any package

I want to implement OTP verification screen without any package.
when i entered the number it should move to next input field
I m using this code in my current project take a refrence this will help
class Otp extends StatefulWidget {
final String? phnNumber;
final String ? code;
String? from;
Otp({Key ?key, this.phnNumber, this.from, this.code}) : super(key:
key);
#override
_OtpState createState() => _OtpState();
}
class _OtpState extends State<Otp> {
double ? height ;
double ? width;
TextEditingController ? contrller1;
TextEditingController ? contrller2;
TextEditingController ? contrller3;
TextEditingController ? contrller4;
SendOtpRequest resend = SendOtpRequest();
SharedPreferences ? prefs;
getSharedPreferences () async
{
prefs = await SharedPreferences.getInstance();
}
String Code = "";
#override
void initState() {
// TODO: implement initState
super.initState();
contrller1 = TextEditingController();
contrller2 = TextEditingController();
contrller3 = TextEditingController();
contrller4 = TextEditingController();
getSharedPreferences();
}
#override
Widget build(BuildContext context) {
height= MediaQuery.of(context).size.height;
width = MediaQuery.of(context).size.height;
final verifyprovider = Provider.of<PostDataProvider>(context);
return Scaffold(
resizeToAvoidBottomInset: false,
appBar: AppBar(
toolbarHeight:height! * 0.07802345,
titleSpacing: 0,
backgroundColor: HexColor("#18263d"),
automaticallyImplyLeading: false,
leading: Padding(
padding: const EdgeInsets.only(left: 8.0,),
child: GestureDetector(
onTap: () {
Navigator.pop(context);
},
child: Container(
color: Colors.transparent,
child: Image.asset("assets/images/back_ic-1.png")),
),
),
// SizedBox(width: width!*0.001234,),
title:Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
height: height!/15,
width: height!/15,
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
width: 2,
color:HexColor("#fc4f00"),
)),
child: Padding(
padding: const EdgeInsets.all(1.0),
child: Container(
height: height!/11,
width: height!/11,
decoration: BoxDecoration(
image: const DecorationImage(
image:
AssetImage("assets/images/home_logo.png"),
fit: BoxFit.fill
),
shape: BoxShape.circle,
border: Border.all(
width: 1,
color:HexColor("#fc4f00"),
)),
),
),
),
SizedBox(width: width! * 0.04234,),
Padding(
padding: const EdgeInsets.only(bottom: 8.0),
child: Text("Verification",
style: GoogleFonts.oswald(fontWeight: FontWeight.bold,
color: Colors.white,
fontSize: width! * 0.03345
),),
),
],
) ,
),
body: SafeArea(
child: Padding(
padding: EdgeInsets.symmetric(vertical: 24, horizontal: 32),
child: Column(
children: [
Text("We have send verification code on your mobile number",
style: GoogleFonts.oswald(fontStyle: FontStyle.normal,
fontSize: width!*0.0234,
color: HexColor("#8b8b8b")),
),
SizedBox(height: height!/38,),
Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
_textFieldOTP(first: true, last: false,controllerr:
contrller1),
_textFieldOTP(first: false, last: false,controllerr:
contrller2),
_textFieldOTP(first: false, last: false,controllerr:
contrller3),
_textFieldOTP(first: false, last: true, controllerr:
contrller4),
],
),
Padding(
padding: const EdgeInsets.all(8.0),
child: InkWell(
onTap:() {
resend.phoneNumber= widget.phnNumber;
resend.countryCode = widget.code;
verifyprovider.resendOtp(context,
jsonEncode(resend));
},
child: Text("Resend OTP?",
style: GoogleFonts.oswald(fontStyle:
FontStyle.normal,
fontSize: width!*0.0234,
color: HexColor("#fc4f00")),
),
),
),
SizedBox(height: height!/28,),
GestureDetector(
onTap: (){
if(contrller1!.text.isNotEmpty&&
contrller2!.text.isNotEmpty&&contrller3!.
text.isNotEmpty&&contrller4!.text.isNotEmpty){
verifyOtpRequest verify = verifyOtpRequest();
verify.phoneNumber = widget.phnNumber;
verify.otp=
contrller1!.text+contrller2!.
text+contrller3!.text+contrller4!.text;
verifyprovider.otpVerification(context,
jsonEncode(verify), widget.from);
}else{
CommonUtils.showToast(msg: "Please fill all the
fields ");
}
},
child: Container(
height: height!/18,
width: width,
decoration: BoxDecoration(
color: HexColor("#fc4f00"),
borderRadius: BorderRadius.circular(10)
),
child: Center(
child: Text("Verify",style: TextStyle(
color: Colors.white,
fontSize: width!*0.02345
),),
)
),
),
],
),
],
),
),
),
);
}
Widget _textFieldOTP({bool ? first, last,
TextEditingController ?
controllerr}) {
return Container(
height:height!/12 ,
child: AspectRatio(
aspectRatio: 1.0,
child: TextField(
controller: controllerr,
autofocus: true,
onChanged: (value) {
if (value.length == 1 && last == false) {
FocusScope.of(context).nextFocus();
}
if (value.length == 0 && first == false) {
FocusScope.of(context).previousFocus();
}
},
showCursor: false,
readOnly: false,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
keyboardType: TextInputType.number,
maxLength: 1,
decoration: InputDecoration(
counter: Offstage(),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(width: 2, color: Colors.black54),
borderRadius: BorderRadius.circular(12)),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(width: 2, color: Colors.black54),
borderRadius: BorderRadius.circular(12)),
),
),
),
);
}
}
When the length of the input data reaches one, you will have to change the text field focus node.
For Example
If you are in the first field, and you enter a number field one focus should be lost, and field two should be in focus. This can be done, by requestFocus.
This article will of help for you: Flutter Focus

ui is different in different devices in flutter

I have designed a ui using flutter first I checked it in my phone which is Moto g5s plus the ui looks goods and I occupies entire screen but when I open the same app in iPhone 11 pro max I am getting a huge empty space but when I open it in iPhone 8 then the ui looks fine as it is in Moto g5s plus. I want to know how to have same consistent ui across different device sizes in flutter?
class Login extends StatefulWidget
{
#override
State<StatefulWidget> createState() {
return LoginState();
}
}
class LoginState extends State<Login>
{
String _email,_password;
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
#override
void initState()
{
super.initState();
}
Widget _progressBar(AuthProvider authProvider)
{
//print("progress"+authProvider.progressStatus.toString());
return Visibility(
maintainSize: true,
maintainAnimation: true,
maintainState: true,
visible: authProvider.progressStatus,
child: Container(
child: Center(
child: SizedBox(
width: 60,
height: 60,
child: Stack(
children: <Widget>[
Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.grey,
offset: Offset(0.0, 1.0), //(x,y)
blurRadius: 1.0,
),
],
),
),
Center(
child: CircularProgressIndicator(),
)
],
),
)
)
),
);
}
Widget _emailTextField(AuthProvider authProvider)
{
return TextFormField(
onChanged: (String value){
authProvider.checkEmail(value);
},
decoration: InputDecoration(
labelText: "Email id",
errorText: authProvider.emailStatus ? null : "Enter a valid email",
border: OutlineInputBorder(
borderRadius: new BorderRadius.circular(32.0),
)
),
keyboardType: TextInputType.emailAddress,
validator: (String value){
if(value.isEmpty || !RegExp(r"[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*#(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?").hasMatch(value))
{
return "Enter a valid email";
} else {
return null;
}
},
onSaved: (String value){
_email = value;
},
);
}
Widget _passwordTextField(AuthProvider authProvider)
{
//print("pass check "+authProvider.passStatus.toString());
return TextFormField(
decoration: InputDecoration(labelText: "Password",
filled: true,
errorText: authProvider.passStatus ? null : "Password is too short",
border: OutlineInputBorder(
borderRadius: new BorderRadius.circular(32.0),
),
fillColor: Colors.white
),
keyboardType: TextInputType.text,
obscureText: true,
onChanged: (String value){
authProvider.checkPassword(value);
},
validator: (String value){
if(value.isEmpty)
{
return "Enter a valid password";
}
else if(value.length < 8)
{
return "Password is too short";
}
else
{
return null;
}
},
onSaved: (String value){
_password = value;
},
);
}
void _login(AuthProvider authProvider)
{
if(!_formKey.currentState.validate())
{
return;
}
_formKey.currentState.save();
Map<String,String> map = new Map();
map['email'] = _email;
map['password'] = _password;
authProvider.login(map);
}
#override
Widget build(BuildContext context) {
final authProvider = Provider.of<AuthProvider>(context);
if(authProvider.loginStatus != null && authProvider.loginStatus != "success")
{
_scaffoldKey.currentState.showSnackBar(SnackBar(
content: Text('${authProvider.loginStatus}',
style: TextStyle(color: Colors.black),),
backgroundColor: Color(0xFFe5e5e5),
));
}
return Scaffold(
key: _scaffoldKey,
body: Stack(
children: <Widget>[
SingleChildScrollView(
child: Container(
child: Column(
children: <Widget>[
Container(
alignment: Alignment.center,
margin: EdgeInsets.fromLTRB(0, 48, 0, 0),
child: Text(
"Take Orders",
style: TextStyle(color: Theme.of(context).primaryColorDark,fontSize: 20),
),
),
Container(
child: Text(
"Track the Best Selling Items",
style: TextStyle(color: Theme.of(context).primaryColor,fontSize: 16),
),
),
Container(
margin: EdgeInsets.fromLTRB(16, 0, 16, 0),
child: SvgPicture.asset('assets/images/undraw_booking.svg',width: 100.0,height: 280.0,),
),
Container(
margin: EdgeInsets.fromLTRB(16, 0, 0, 0),
child:Row(
children: <Widget>[
Text(
"Login To ",
style: TextStyle(color: Colors.black,fontSize: 20)
),
Text(
"Take orders",
style: TextStyle(color: Theme.of(context).primaryColorDark,fontSize: 20),
)
],
),
),
Container(
margin: EdgeInsets.fromLTRB(16, 8, 16, 0),
child: Form(
key: _formKey,
child: Column(
children: <Widget>[
//_emailTextField(_loginBloc),
Container(
margin: EdgeInsets.fromLTRB(0, 8, 0, 0),
child: _emailTextField(authProvider),
),
Container(
margin: EdgeInsets.fromLTRB(0, 8, 0, 0),
child: _passwordTextField(authProvider),
),
Container(
margin: EdgeInsets.fromLTRB(0, 8, 0, 0),
child: Align(
alignment: Alignment.centerLeft,
child: RaisedButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(32.0)
),
padding: EdgeInsets.fromLTRB(64, 12, 64, 12),
color: Theme.of(context).accentColor,
textColor: Colors.white,
child: Text(
"Login",
),
onPressed: (){
_login(authProvider);
},
) ,
),
),
],
),
),
),
],
),
)
),
_progressBar(authProvider),
],
),
);
}
}
images of emulator
without seeing code i cannot advise you proper solution however, i guess that tricks will solve your many issues.
instead of using fixed values
try to use
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
you can also use them like
height: MediaQuery.of(context).size.height * 0.80, // 80% of screen height
width: MediaQuery.of(context).size.width * 0.35, // 35% of screen width
Hope will help you

Syntax highlighter doesn't expand to show all code

I am trying to come up with a code editor which takes input from a text form field and shows the output on a Rich Text widget using DartSyntaxHighlighter.
While it works fine for a short snippet of code, it doesn't show all the code for a larger snippet. Here's what I've done so far :
class CodeEditorWidget extends StatefulWidget {
CodeEditorWidget();
#override
_ContentWidgetState createState() {
return _ContentWidgetState();
}
}
class _ContentWidgetState extends BaseState<CodeEditorWidget> {
String _currentCode = "";
#override
void initializeData() {
_currentCode = "class HelloWorld {\n"
"public static void main() {\n"
"System.out.println(\"Hello again\");\n"
"}\n"
"}";
_contentController.addListener(() {
_currentCode = _contentController.value.text;
setState(() {
});
});
}
#override
Widget build(BuildContext context) => _buildContent();
Widget _buildContent() {
//return _buildBody();
userState = AppStateWidget.of(context).userState;
return _buildBody();
}
Scaffold _buildBody() => Scaffold(
key: _scaffoldLoginKey,
appBar: buildAppBar("Code Editor"),
body: _buildCodeEditor(),
floatingActionButtonLocation: FloatingActionButtonLocation.endFloat,
floatingActionButton: _buildFab(),
);
_buildCodeEditor() => Card(
margin: const EdgeInsets.fromLTRB(BaseState.horizontalMargin, 0, BaseState.horizontalMargin, 0),
child: Column(
children: <Widget>[
Expanded(
child: _buildCodeView()//buildSyntaxCodeBlock(_currentCode, 12)//_buildCodeView(),
),
_buildInputContainer()
],
),
);
_buildCodeView() => SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Container(
width: double.infinity,
height: double.maxFinite,
padding: EdgeInsets.all(12),
decoration: BoxDecoration(color: Colors.black),
child: RichText(
text: TextSpan(
style: TextStyle(fontFamily: 'VarelaRound-Regular', fontSize: 12),
children: <TextSpan>[
DartSyntaxHighlighter(SyntaxHighlighterStyle.darkThemeStyle()).format(_currentCode)
],
),
),
),
),
);
Container _buildInputContainer() {
return Container(
color: Colors.grey,
padding: EdgeInsets.all(8),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
_buildInputLayout(),
],
),
);
}
_buildInputLayout() => Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[_buildTextForm()],
);
Widget _buildTextForm() => Flexible(
child: Container(
color: Colors.white,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
style: buildTextStyleBlack(16),
decoration: InputDecoration.collapsed(hintText: "Type here..."),
maxLines: 10,
validator: _validateEmptyCode,
controller: _contentController,
keyboardType: TextInputType.multiline,
onSaved: (String contentString) {
//_currentCode = contentString;
},
),
),
),
);
String _validateEmptyCode(String value) {
return value.isEmpty ? "Required" : null;
}
var _contentController = TextEditingController();
_buildFab() => FloatingActionButton(
onPressed: () {
setState(() {
});
},
child: Icon(Icons.add),
foregroundColor: Colors.white,
backgroundColor: Colors.green,
);
var _scaffoldLoginKey = GlobalKey<ScaffoldState>();
_showSnackBar(String message) => _scaffoldLoginKey.currentState
.showSnackBar(SnackBar(content: Text(message, style: buildTextStyle(16),)));
}
Here's a screen shot for reference :
This is a web page I am trying to build in flutter.
For me, this piece of code is doing what you are trying to acheive.
TextEditingController text1Controller = new TextEditingController();
TextEditingController text2Controller = new TextEditingController();
#override
Widget build(BuildContext context) {
Size screenSize = MediaQuery.of(context).size;
return new Scaffold(
backgroundColor: Colors.white,
appBar: new PreferredSize(
preferredSize: new Size(screenSize.width, 55.0),
child: new AppBar(
elevation: 5.0,
title : new Text(
"Code Editor",
style: new TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 18.0)),
centerTitle: true,
backgroundColor: Colors.blue,
),
),
body: Container(
child: Column(
children: <Widget>[
new Padding(padding: EdgeInsets.only(bottom: 20.0, top: 20.0)),
new TextField(
onChanged: (text) {
setState(() {
text2Controller.text = text;
});
},
controller: text1Controller,
keyboardType: TextInputType.text,
autofocus: false,
decoration: InputDecoration(
contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
focusedBorder: OutlineInputBorder(borderSide: const BorderSide(color: Colors.black, width: 2.0)),
),
),
new Padding(padding: EdgeInsets.only(bottom: 20.0)),
new TextField(
controller: text2Controller,
keyboardType: TextInputType.text,
autofocus: false,
decoration: InputDecoration(
contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
focusedBorder: OutlineInputBorder(borderSide: const BorderSide(color: Colors.black, width: 2.0)),
),
)
],),),
);
}

TextFormField losing value when changing focus

I am trying to move to other TextFormField but whenever I lose focus from first TextFormField text became empty, I search about this issue but I don't find any solution till now.
var _formKey = GlobalKey<FormState>();
Note note;
TextEditingController titleController=TextEditingController();
TextEditingController descriptionController=TextEditingController();
#override
Widget build(BuildContext context) {
TextStyle textStyle=Theme.of(context).textTheme.title;
titleController.text=note.title;
descriptionController.text=note.description;
// TODO: implement build
return WillPopScope(
onWillPop: (){
moveToLastScreen();
},
child:Scaffold(
appBar: AppBar(
title: Text("appBarTitle"),
leading: IconButton(icon:Icon(Icons.arrow_back),onPressed: (){
moveToLastScreen();
},),
),
body: Form(
key: _formKey,
child: Padding(
padding: EdgeInsets.only(top: 15.0,left: 15.0,right: 10.0),
child: ListView(
children: <Widget>[
//1st element
Padding(
padding: EdgeInsets.only(top: 15.0,bottom: 15.0,),
child: TextFormField(
validator: (String value){
if(value.isEmpty)
{
return "Please enter Title";
}
},
controller: titleController,
style: textStyle,
onSaved: (value){
debugPrint("Something changed in title Text field");
updateTitle();
},
/*onChanged: (value){
debugPrint("Something changed in title Text field");
updateTitle();
},*/
decoration: InputDecoration(
labelText: "Title",
labelStyle: textStyle,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5.0)
)
),
),
),
//2nd element
Padding(
padding: EdgeInsets.only(top: 15.0,bottom: 15.0,),
child: TextFormField(
validator: (String value){ //2nd step for form with validation
if(value.isEmpty)
{
return "Please enter principle amount";
}
},
onSaved: (value){
debugPrint("Something changed in Description Text field");
updateDescription();
},
controller: descriptionController,
style: textStyle,
/*onChanged: (value){
debugPrint("Something changed in Description Text field");
updateDescription();
},*/
decoration: InputDecoration(
labelText: "Description",
labelStyle: textStyle,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5.0)
)
),
),
),
//3th element
Padding(
padding: EdgeInsets.only(top: 15.0,bottom: 15.0),
child: Row(
children: <Widget>[
Expanded(
child: RaisedButton(
color: Theme.of(context).primaryColorDark,
textColor: Theme.of(context).primaryColorLight,
child: Text("Save",textScaleFactor: 1.5,),
onPressed: (){
setState(() {
if(_formKey.currentState.validate()) {
debugPrint("Save Pressed");
_save();
}
});
}
),
),
Container(width: 5.0,),
Expanded(
child: RaisedButton(
color: Theme.of(context).primaryColorDark,
textColor: Theme.of(context).primaryColorLight,
child: Text("Delete",textScaleFactor: 1.5,),
onPressed: (){
setState(() {
debugPrint("Delete Pressed");
_delete();
});
}
),
),
],
),
),
],
),
)),
));
}
Please suggest me I am new in flutter.
Remove titleController.text=note.title; descriptionController.text=note.description; from your build method and place it in initState method.
You will lose the value in the textField because those lines get executed anytime there is a rebuild, thereby replacing the values gotten from the textFields and replacing it with note.title and note.description which are empty at that point.
In other words, remove those lines and add this to your code.
#override
void initState() {
super.initState();
titleController.text=note.title;
descriptionController.text=note.description;
}