Call a function whenever there is a change in Flutter - flutter

how can I call a function whenever there is a change in TextFormField .
I have many of them and it's more like an invoice.
So whenever the user changes a value, I need to make some mathematical operations.
The problem is that sometimes some TextFormField could be NULL (User did'tn insert a value yet) and that causes an error.
import 'package:flutter/material.dart';
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
late TextEditingController age = TextEditingController();
late TextEditingController height = TextEditingController();
late TextEditingController weight = TextEditingController();
late TextEditingController result = TextEditingController();
return Scaffold(
appBar: AppBar(
title: const Text('BMI !'),
),
body: Center(
child: DecoratedBox(
decoration: const BoxDecoration(
color: Colors.white10,
),
child: Padding(
padding: const EdgeInsets.all(48.0),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextFormField(
controller:age,
decoration: const InputDecoration(
border: UnderlineInputBorder(),
labelText: 'AGE',
),
),
TextFormField(
controller:height,
decoration: const InputDecoration(
border: UnderlineInputBorder(),
labelText: 'HEIGHT',
),
),
TextFormField(
controller:weight,
decoration: const InputDecoration(
border: UnderlineInputBorder(),
labelText: 'WEIGHT',
),
),
TextFormField(
enabled:false,
controller:result,
decoration: const InputDecoration(
border: UnderlineInputBorder(),
labelText: 'Result',
),
),
],
),
),
),
),
);
}
}
void main() {
runApp(
MaterialApp(
home: MyApp(),
),
);
}

To call a function every time the TextFormField has a change, there's a property for exactly that!
the onChanged property, which fires every time something is typed:
return TextFormField(
onChanged: (value) {
// do something with `value`
},);
Since this is only called once there's a change, you don't have to worry about null
Edit: you can check if the controler.isNotEmpty and do something based on that:
void onChanged(String value){
if (_controller.text.isNotEmpty && _secondController.text.isNotEmpty) {
// do something
} else {
// do something
}
}
return TextFormField(
controller: _controller,
onChanged: (value) => onChanged(value),);

Related

Flutter / Dart - change Column to Row and display the result Realtime

Flutter / Dart - I have a simple app but am new to programming, so struggling.
Currently, the setup is with all the TextInput boxes in a Column. I would like to change this to having them in a Row. I assumed this would be easy by simply replacing the Word Column with Row on line 44. But it doesn't work and when I try to run it, the "errors_patch.dart" page opens (which I have never seen before) with a highlighted error on line 51 "int assertionStart, int assertionEnd, Object? message);".
How can I simply change from Column to Row?
How can I have the result show in real time rather than needing to click on the "Subtraction" button to get it?
Many thanks in advance.
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
#override
Widget build(BuildContext context) {
const appTitle = 'Help with a meal....';
return MaterialApp(
debugShowCheckedModeBanner: false,
title: appTitle,
home: Scaffold(
appBar: AppBar(
title: const Text(appTitle),
backgroundColor: Colors.grey,
foregroundColor: Colors.black,
),
body: const AddTwoNumbers(),
),
);
}
}
class AddTwoNumbers extends StatefulWidget {
const AddTwoNumbers({super.key});
#override
// ignore: library_private_types_in_public_api
_AddTwoNumbersState createState() => _AddTwoNumbersState();
}
class _AddTwoNumbersState extends State<AddTwoNumbers> {
TextEditingController num1controller = TextEditingController();
TextEditingController num2controller = TextEditingController();
TextEditingController num3controller = TextEditingController();
TextEditingController num4controller = TextEditingController();
String result = "0";
#override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.all(10.0),
child: Column(
children: <Widget>[
TextField(
keyboardType: const TextInputType.numberWithOptions(decimal: true),
controller: num1controller,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Target Level',
hintText: 'Enter First Number',
),
),
const SizedBox(
height: 8,
),
TextField(
keyboardType: const TextInputType.numberWithOptions(decimal: true),
controller: num2controller,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Current Level',
hintText: 'Enter Second Number',
),
),
const SizedBox(
height: 8,
),
TextField(
keyboardType: const TextInputType.numberWithOptions(decimal: true),
controller: num3controller,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Current Meal carbs',
hintText: 'Enter Third Number',
),
),
const SizedBox(
height: 8,
),
TextField(
keyboardType: const TextInputType.numberWithOptions(decimal: true),
controller: num4controller,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Current Meal carbs 2',
hintText: 'Enter Fourth Number',
),
),
const SizedBox(
height: 8,
),
Wrap(children: [
ElevatedButton(
style: ElevatedButton.styleFrom(
foregroundColor: Colors.white,
backgroundColor: Colors.purple),
child: const Text("Subtraction"),
onPressed: () {
setState(() {
double sum = double.parse(num1controller.text) -
double.parse(num2controller.text);
result = sum.toStringAsFixed(1);
});
},
),
const SizedBox(
height: 20,
width: 20,
),
]),
Text('Difference between Target Level and Current Level: $result'),
],
),
);
}
}
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
#override
Widget build(BuildContext context) {
const appTitle = 'Help with a meal....';
return MaterialApp(
debugShowCheckedModeBanner: false,
title: appTitle,
home: Scaffold(
appBar: AppBar(
title: const Text(appTitle),
backgroundColor: Colors.grey,
foregroundColor: Colors.black,
),
body: const AddTwoNumbers(),
),
);
}
}
class AddTwoNumbers extends StatefulWidget {
const AddTwoNumbers({super.key});
#override
// ignore: library_private_types_in_public_api
_AddTwoNumbersState createState() => _AddTwoNumbersState();
}
class _AddTwoNumbersState extends State<AddTwoNumbers> {
TextEditingController num1controller = TextEditingController();
TextEditingController num2controller = TextEditingController();
TextEditingController num3controller = TextEditingController();
TextEditingController num4controller = TextEditingController();
String result = "0";
_calculate() {
if (num1controller.text.isNotEmpty && num2controller.text.isNotEmpty) {
setState(() {
double sum = double.parse(num1controller.text) -
double.parse(num2controller.text);
result = sum.toStringAsFixed(1);
});
}
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: Container(
padding: const EdgeInsets.all(10.0),
child: Column(
children: [
Row(
children: <Widget>[
Expanded(
child: TextField(
onChanged: (value) => _calculate(),
keyboardType:
const TextInputType.numberWithOptions(decimal: true),
controller: num1controller,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Target Level',
hintText: 'Enter First Number',
),
),
),
const SizedBox(
width: 8,
),
Expanded(
child: TextField(
onChanged: (value) => _calculate(),
keyboardType:
const TextInputType.numberWithOptions(decimal: true),
controller: num2controller,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Current Level',
hintText: 'Enter Second Number',
),
),
),
const SizedBox(
width: 8,
),
Expanded(
child: TextField(
onChanged: (value) => _calculate(),
keyboardType:
const TextInputType.numberWithOptions(decimal: true),
controller: num3controller,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Current Meal carbs',
hintText: 'Enter Third Number',
),
),
),
const SizedBox(
width: 8,
),
Expanded(
child: TextField(
onChanged: (value) => _calculate(),
keyboardType:
const TextInputType.numberWithOptions(decimal: true),
controller: num4controller,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Current Meal carbs 2',
hintText: 'Enter Fourth Number',
),
),
),
const SizedBox(
width: 8,
),
],
),
Text(
'Difference between Target Level and Current Level: $result'),
],
),
),
),
);
}
}
Since you are switching to Row it doesn't know the width of the TextFields, so you need to wrap them with Expanded or Flexible widgets to make them take the space they need (or you can give them some fixed width if you wish), something like in the solution below. And the answer to the second question is also in the solution, you just call the calculate method on every TextField change.
class AddTwoNumbers extends StatefulWidget {
const AddTwoNumbers({Key? key}) : super(key: key);
#override
// ignore: library_private_types_in_public_api
_AddTwoNumbersState createState() => _AddTwoNumbersState();
}
class _AddTwoNumbersState extends State<AddTwoNumbers> {
TextEditingController num1controller = TextEditingController();
TextEditingController num2controller = TextEditingController();
TextEditingController num3controller = TextEditingController();
TextEditingController num4controller = TextEditingController();
String result = "0";
_calculate() {
setState(() {
double sum =
double.parse(num1controller.text) - double.parse(num2controller.text);
result = sum.toStringAsFixed(1);
});
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: Container(
padding: const EdgeInsets.all(10.0),
child: Column(
children: [
Row(
children: <Widget>[
Expanded(
child: TextField(
onChanged: (value) => _calculate(),
keyboardType:
const TextInputType.numberWithOptions(decimal: true),
controller: num1controller,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Target Level',
hintText: 'Enter First Number',
),
),
),
const SizedBox(
width: 8,
),
Expanded(
child: TextField(
onChanged: (value) => _calculate(),
keyboardType:
const TextInputType.numberWithOptions(decimal: true),
controller: num2controller,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Current Level',
hintText: 'Enter Second Number',
),
),
),
const SizedBox(
width: 8,
),
Expanded(
child: TextField(
onChanged: (value) => _calculate(),
keyboardType:
const TextInputType.numberWithOptions(decimal: true),
controller: num3controller,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Current Meal carbs',
hintText: 'Enter Third Number',
),
),
),
const SizedBox(
width: 8,
),
Expanded(
child: TextField(
onChanged: (value) => _calculate(),
keyboardType:
const TextInputType.numberWithOptions(decimal: true),
controller: num4controller,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Current Meal carbs 2',
hintText: 'Enter Fourth Number',
),
),
),
const SizedBox(
width: 8,
),
],
),
Text(
'Difference between Target Level and Current Level: $result'),
],
),
),
),
);
}
}
There are many ways to do what you're trying to achieve. For changing Column to Rows, you can use a container with a column as a child and rows as children in it. You can see the documentation for further assistance.
For your second question, you can use onChanged() callback or you can use TextEditingController to see the realtime changes in your TextField.

Validate Elevated Button in Flutter

I'm making an app using Flutter which calculates motor vehicle tax.
It calculates it perfectly fine when I enter the cost of vehicle.
But I want to add a validation to it. When I don't enter any cost of vehicle and keeps it empty and then click the calculate button, I want it show - please enter the cost.
How do I add this validation as this is not a form.
Here is the code of that part:
TextField(
controller: costController,
decoration: const InputDecoration(labelText: "Cost of Vehicle"),
keyboardType: TextInputType.number,
inputFormatters: <TextInputFormatter>[
FilteringTextInputFormatter.digitsOnly
],
),
const SizedBox(
height: 20,
),
ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Theme.of(context).primaryColor,
),
onPressed: () {
setState(() {
toPrint = calc(
dropDownValue!,
int.parse(costController.text),
).toString();
});
},
child: const Text("Calculate")),
const SizedBox(
height: 20,
),
Container(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
decoration: BoxDecoration(
color: Colors.lightGreenAccent[100],
border: const Border(
bottom: BorderSide(color: Colors.grey),
)),
child: Text("Tax : $toPrint "),
),
Wrap the column with a Form widget add avalidator to the textfield
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
#override
Widget build(BuildContext context) {
const appTitle = 'Form Validation Demo';
return MaterialApp(
title: appTitle,
home: Scaffold(
appBar: AppBar(
title: const Text(appTitle),
),
body: const MyCustomForm(),
),
);
}
}
// Create a Form widget.
class MyCustomForm extends StatefulWidget {
const MyCustomForm({super.key});
#override
MyCustomFormState createState() {
return MyCustomFormState();
}
}
// Create a corresponding State class.
// This class holds data related to the form.
class MyCustomFormState extends State<MyCustomForm> {
// Create a global key that uniquely identifies the Form widget
// and allows validation of the form.
//
// Note: This is a GlobalKey<FormState>,
// not a GlobalKey<MyCustomFormState>.
final _formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
// Build a Form widget using the _formKey created above.
return Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextField(
controller: costController,
decoration: const InputDecoration(labelText: "Cost of Vehicle"),
keyboardType: TextInputType.number,
inputFormatters: <TextInputFormatter>[
FilteringTextInputFormatter.digitsOnly
],
// The validator receives the text that the user has entered.
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter some text';
}
return null;
},
),
ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Theme.of(context).primaryColor,
),
onPressed: () {
if (_formKey.currentState!.validate()) {
setState(() {
toPrint = calc(
dropDownValue!, int.parse(costController.text),
).toString();
});
}
},
child: const Text("Calculate")),
const SizedBox(
height: 20,
),
Container(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
decoration: BoxDecoration(
color: Colors.lightGreenAccent[100],
border: const Border(
bottom: BorderSide(color: Colors.grey),
)),
child: Text("Tax : $toPrint "),
),
],
),
);
}
}
Use Form Widget and Convert TextField to TextFormField like that.
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class FormWidget extends StatefulWidget {
const FormWidget({Key? key}) : super(key: key);
#override
State<FormWidget> createState() => _FormWidgetState();
}
class _FormWidgetState extends State<FormWidget> {
final TextEditingController costController = TextEditingController();
final _formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
return Scaffold(
key: _formKey,
body: Column(
children: [
Form(
child: TextFormField(
validator: (value) {
if (value.isEmpty) {
return "Please enter the cost.";
}
return null;
},
controller: costController,
decoration: const InputDecoration(labelText: "Cost of Vehicle"),
keyboardType: TextInputType.number,
inputFormatters: <TextInputFormatter>[
FilteringTextInputFormatter.digitsOnly
],
),
),
const SizedBox(
height: 20,
),
ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Theme.of(context).primaryColor,
),
onPressed: () {
if(_formKey.currentState.validate()){
//do your setState stuff
setState(() {
});
}
},
child: const Text("Calculate")),
const SizedBox(
height: 20,
),
Container(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
decoration: BoxDecoration(
color: Colors.lightGreenAccent[100],
border: const Border(
bottom: BorderSide(color: Colors.grey),
)),
child: Text("Tax : "),
),
],
),
);
}
}

How to set Background image properly in to my code

I want to set background image in to my code but I got this error "Another exception was thrown: Unable to load asset: assets/Onepiece-1.jpg" this one is the error actually it is not an error but the image doesn't appear in the background. I already set my image to in pubspec.yml.I just don't know how to set properly in my code and i dont know what the problem is can some one help my how to fix this error.
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Registration Form',
theme: ThemeData(
primarySwatch: Colors.teal,
),
home: const MyHomePage(title: 'Registration'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
TextEditingController nameController = TextEditingController();
TextEditingController nameController2 = TextEditingController();
TextEditingController nameController3 = TextEditingController();
bool showPassword = false;
TextEditingController nameController4 = TextEditingController();
TextEditingController nameController5 = TextEditingController();
TextEditingController nameController6 = TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
floatingActionButton: FloatingActionButton.extended(
onPressed: () {},
label: Text('Register'),
icon: const Icon(Icons.upload_file_sharp),
),
body: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/Onepiece-1.jpg"),
fit: BoxFit.cover,
),
),
child: Column(
children: <Widget>[
Container(
margin: EdgeInsets.all(15),
child: TextField(
controller: nameController,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Username',
),
onChanged: (Text) {
setState(() {});
},
)),
Container(
margin: EdgeInsets.all(15),
child: TextField(
controller: nameController2,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Email Address',
),
onChanged: (Text) {
setState(() {});
},
)),
Container(
margin: EdgeInsets.all(15),
child: TextField(
controller: nameController3,
obscureText: showPassword,
obscuringCharacter: "*",
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Password',
),
onChanged: (Text) {
setState(() {});
},
)),
Container(
margin: EdgeInsets.all(15),
child: TextField(
controller: nameController4,
obscureText: showPassword,
obscuringCharacter: "*",
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Confirm Password',
),
onChanged: (Text) {
setState(() {});
},
)),
TextButton(
onPressed: () {
setState(() {
showPassword = !showPassword;
});
},
child: Text('Show / Hide Password')
),
Container(
margin: EdgeInsets.all(15),
child: TextField(
controller: nameController5,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Address',
),
onChanged: (Text) {
setState(() {});
},
)),
Container(
margin: EdgeInsets.all(15),
child: TextField(
controller: nameController6,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Phone Number',
),
onChanged: (Text) {
setState(() {});
},
)),
])));
}
}
assets Directory
pubspec.yaml
assets:
- assets/images/
source code
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Registration Form',
theme: ThemeData(
primarySwatch: Colors.teal,
),
home: const MyHomePage(title: 'Registration'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
TextEditingController nameController = TextEditingController();
TextEditingController nameController2 = TextEditingController();
TextEditingController nameController3 = TextEditingController();
bool showPassword = false;
TextEditingController nameController4 = TextEditingController();
TextEditingController nameController5 = TextEditingController();
TextEditingController nameController6 = TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
floatingActionButton: FloatingActionButton.extended(
onPressed: () {},
label: Text('Register'),
icon: const Icon(Icons.upload_file_sharp),
),
body: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/images/1-1.JPG"),
fit: BoxFit.cover,
),
),
child: Column(
children: <Widget>[
Container(
margin: EdgeInsets.all(15),
child: TextField(
controller: nameController,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Username',
),
onChanged: (Text) {
setState(() {});
},
)),
Container(
margin: EdgeInsets.all(15),
child: TextField(
controller: nameController2,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Email Address',
),
onChanged: (Text) {
setState(() {});
},
)),
Container(
margin: EdgeInsets.all(15),
child: TextField(
controller: nameController3,
obscureText: showPassword,
obscuringCharacter: "*",
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Password',
),
onChanged: (Text) {
setState(() {});
},
)),
Container(
margin: EdgeInsets.all(15),
child: TextField(
controller: nameController4,
obscureText: showPassword,
obscuringCharacter: "*",
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Confirm Password',
),
onChanged: (Text) {
setState(() {});
},
)),
TextButton(
onPressed: () {
setState(() {
showPassword = !showPassword;
});
},
child: Text('Show / Hide Password')
),
Container(
margin: EdgeInsets.all(15),
child: TextField(
controller: nameController5,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Address',
),
onChanged: (Text) {
setState(() {});
},
)),
Container(
margin: EdgeInsets.all(15),
child: TextField(
controller: nameController6,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Phone Number',
),
onChanged: (Text) {
setState(() {});
},
)),
])));
}
}

How to add extra text boxes in flutter

https://petercoding.com/firebase/2020/02/25/using-firebase-auth-in-flutter/
Hi all I am new to flutter and following the above guide.
We create four textformfields and each field will contain its own validation. After that we create a Raisedbutton widget that will be the submit button:
How do I actually do this as this only adds 1? Where do I add the others, within this widget. Sorry for noob question
return Form(
key: _formKey,
child: SingleChildScrollView(
child: Column(children: <Widget>[
Padding(
padding: EdgeInsets.all(20.0),
child: TextFormField(
controller: nameController,
decoration: InputDecoration(
labelText: "Enter User Name",
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10.0),
),
),
// The validator receives the text that the user has entered.
validator: (value) {
if (value.isEmpty) {
return 'Enter User Name';
}
return null;
},
),
),
Thank you in advance
You can copy paste run full code below
You can reference https://flutter.dev/docs/cookbook/forms/validation
code snippet
Padding(
padding: EdgeInsets.all(20.0),
child: TextFormField(
controller: passwordController,
obscureText: true,
decoration: InputDecoration(
labelText: "Enter password",
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10.0),
),
),
// The validator receives the text that the user has entered.
validator: (value) {
if (value.isEmpty) {
return 'Enter password';
}
return null;
},
),
),
RaisedButton(
onPressed: () {
if (_formKey.currentState.validate()) {}
},
child: Text('Submit'),
)
working demo
full code
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
final _formKey = GlobalKey<FormState>();
TextEditingController emailController = TextEditingController();
TextEditingController nameController = TextEditingController();
TextEditingController passwordController = TextEditingController();
TextEditingController ageController = TextEditingController();
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
void dispose() {
super.dispose();
nameController.dispose();
emailController.dispose();
passwordController.dispose();
ageController.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Form(
key: _formKey,
child: SingleChildScrollView(
child: Column(children: <Widget>[
Padding(
padding: EdgeInsets.all(20.0),
child: TextFormField(
controller: nameController,
decoration: InputDecoration(
labelText: "Enter User Name",
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10.0),
),
),
// The validator receives the text that the user has entered.
validator: (value) {
if (value.isEmpty) {
return 'Enter User Name';
}
return null;
},
),
),
Padding(
padding: EdgeInsets.all(20.0),
child: TextFormField(
controller: emailController,
decoration: InputDecoration(
labelText: "Enter Email",
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10.0),
),
),
// The validator receives the text that the user has entered.
validator: (value) {
if (value.isEmpty) {
return 'Enter Email';
}
return null;
},
),
),
Padding(
padding: EdgeInsets.all(20.0),
child: TextFormField(
controller: ageController,
decoration: InputDecoration(
labelText: "Enter age",
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10.0),
),
),
// The validator receives the text that the user has entered.
validator: (value) {
if (value.isEmpty) {
return 'Enter age';
}
return null;
},
),
),
Padding(
padding: EdgeInsets.all(20.0),
child: TextFormField(
controller: passwordController,
obscureText: true,
decoration: InputDecoration(
labelText: "Enter password",
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10.0),
),
),
// The validator receives the text that the user has entered.
validator: (value) {
if (value.isEmpty) {
return 'Enter password';
}
return null;
},
),
),
RaisedButton(
onPressed: () {
if (_formKey.currentState.validate()) {}
},
child: Text('Submit'),
)
]))),
);
}
}

The prefixIcon of TextField widget in flutter disappears on focusing TextField. How to solve?

Was just exploring flutter and got stuck. The prefixIcon disappears on clicking field and it appears back when focused out. How to solve this ? The code is as below. Tried removing the key of form. I want the icon to stay even if focused in or focused out. Is there any other property to set?
Couldn't be able to find a fix.
class _MyHomePageState extends State<MyHomePage> {
String _email = "";
String _password = "";
final _formKey = GlobalKey<FormState>();
final FocusNode _emailFocus = FocusNode();
final FocusNode _passwordFocus = FocusNode();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Container(
padding: const EdgeInsets.symmetric(horizontal: 50.0,vertical: 100.0),
decoration: BoxDecoration(color: Colors.white),
child:Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
TextFormField(
focusNode: _emailFocus,
decoration: InputDecoration(
labelText: 'Username or email',
prefixIcon: Icon(Icons.person), //prefixIcon
focusedBorder: UnderlineInputBorder(),
hintText: "example#mail.com",
)
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
),
TextFormField(
obscureText: true,
focusNode: _passwordFocus,
decoration: InputDecoration(
labelText: 'Password',
prefixIcon: Icon(Icons.lock),
focusedBorder: UnderlineInputBorder(),
)
) ,
Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
child: RaisedButton(
onPressed: () {
// Validate will return true if the form is valid, or false if
// the form is invalid.
if (_formKey.currentState.validate()) {
// Process data.
}
},
child: Text('Submit'),
),
),
],
),
)
)
);
}
}
The issue was that I had set the primary colour to white. So whenever the field was focused it was disappering as the background was also white. My bad.
the issue came to me when i add TextField to AppBar as title.
to fix this, just add color to icon.
e.g.
prefixIcon: Icon(Icons.person), //prefixIcon
should be replaced with
prefixIcon: Icon(Icons.person, color: Colors.black,), //prefixIcon
i post an issue, but no response yet.
this works fine for me
class MyHomePage extends StatefulWidget {
#override
State<StatefulWidget> createState() {
// TODO: implement createState
return _MyHomePageState();
}
}
class _MyHomePageState extends State<MyHomePage> {
String _email = "";
String _password = "";
final _formKey = GlobalKey<FormState>();
final FocusNode _emailFocus = FocusNode();
final FocusNode _passwordFocus = FocusNode();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('hi'),
),
body: Container(
padding: EdgeInsets.only(top: 50, left: 50, right: 50),
decoration: BoxDecoration(color: Colors.white),
child: Form(
key: _formKey,
child: ListView(
children: <Widget>[
TextFormField(
focusNode: _emailFocus,
decoration: InputDecoration(
labelText: 'Username or email',
prefixIcon: Icon(Icons.person), //prefixIcon
focusedBorder: UnderlineInputBorder(),
hintText: "example#mail.com",
)),
Padding(
padding: EdgeInsets.only(top: 20),
),
TextFormField(
obscureText: true,
focusNode: _passwordFocus,
decoration: InputDecoration(
labelText: 'Password',
prefixIcon: Icon(Icons.lock),
focusedBorder: UnderlineInputBorder(),
)),
Padding(
padding: EdgeInsets.only(top: 20),
child: RaisedButton(
onPressed: () {
// Validate will return true if the form is valid, or false if
// the form is invalid.
if (_formKey.currentState.validate()) {
// Process data.
}
},
child: Text('Submit'),
),
),
],
),
)));
}