Flutter keyboard done button causes textfield content to vanish - flutter

I have 2 textfields in a form. When i click on done button on keyboard in the second text field , keyboard hides and both the text fields get empty. The same happes when i closes the keyboard manually, then also the content of the textfields get lost.
It looks like the screen gets refresh evertime this happens. why is it so?
#override
Widget build(BuildContext context) {
TextEditingController nameTextFieldController = TextEditingController();
TextEditingController emailTextFieldController = TextEditingController();
FocusNode emailFocusNode = new FocusNode();
// TODO: implement build
return WillPopScope(
onWillPop: () {
moveToLastScreen();
},
child: Scaffold(
appBar: AppBar(
title: Text("Signup"),
leading: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {
moveToLastScreen();
}),
),
body: Form(
key: _formKey,
child: Container(
child: ListView(
padding: EdgeInsets.only(top: 20, left: 35, right: 35),
children: <Widget>[
Center(
child: GestureDetector(
onTap: () {
imageSelectorGalary();
},
child: new Container(
width: 100.0,
height: 100.0,
child: _image == null
? new Image.asset(
'images/profilepic.png',
fit: BoxFit.fitWidth,
)
: new CircleAvatar(
backgroundImage: new FileImage(_image),
radius: 200.0,
)))),
Text(
"NAME",
style: TextStyle(fontWeight: FontWeight.bold),
),
Padding(
padding: EdgeInsets.only(top: 5, bottom: 10),
child: TextFormField(
inputFormatters:[
LengthLimitingTextInputFormatter(10),
],
onFieldSubmitted: (String value){
FocusScope.of(context).requestFocus(emailFocusNode);
},
keyboardType: TextInputType.text,
controller: nameTextFieldController,
validator: (String value) {
if (value.isEmpty) {
return 'Please enter the name';
}
},
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5.0)),
contentPadding: EdgeInsets.only(
top: 15, bottom: 15, left: 20, right: 20))),
),
Text(
"EMAIL ID",
style: TextStyle(fontWeight: FontWeight.bold),
),
Padding(
padding: EdgeInsets.only(top: 5, bottom: 10),
child: TextFormField(
controller: emailTextFieldController,
focusNode: emailFocusNode ,
onFieldSubmitted: (String value){
FocusScope.of(context).requestFocus(new FocusNode());
},
validator: (String value){
if(value.isEmpty){
return "Please enter your email-id";
}
},
decoration: InputDecoration(
contentPadding: EdgeInsets.only(
top: 15, bottom: 15, left: 20, right: 20),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5.0))),
),
),
Text(
"CITY AND AREA",
style: TextStyle(fontWeight: FontWeight.bold),
),
GestureDetector(
onTap: () {
CityAreasDialog cityAreasDialog =
new CityAreasDialog();
cityAreasDialog.information(context);
},
child: Container(
margin: EdgeInsets.only(top: 5, bottom: 10),
padding: EdgeInsets.only(left: 20, right: 20),
decoration: new BoxDecoration(
border: new Border.all(color: CustomColors.grey),
borderRadius: BorderRadius.all(Radius.circular(
5.0) // <--- border radius here
)),
child: Container(
padding: EdgeInsets.only(top: 10, bottom: 10),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: <Widget>[
Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: <Widget>[
Text("Select Your City"),
Text(
"and area",
style: TextStyle(
color: Colors.grey, fontSize: 10),
)
],
),
Icon(
Icons.arrow_drop_down,
color: Colors.black,
)
],
)),
)),
Container(
margin: EdgeInsets.only(top: 20, left: 10, right: 10),
child: RaisedButton(
onPressed: () {
debugPrint("Next Click");
onSignup();
},
child: new Text(
"NEXT",
),
))
],
),
)),
));
}

This issue is because you are creating new TextEditingController every time your widget is rebuilt.
So to fix this issue, move these variables nameTextFieldController ,emailTextFieldController outside your build method.
Like this:
TextEditingController nameTextFieldController = TextEditingController();
TextEditingController emailTextFieldController = TextEditingController();
#override
Widget build(BuildContext context) {
...

Related

value of the title and description repeats every time a new todo is made

I just started learning flutter and am trying to create a todo app, but every time a new todo is made the value of the title and the description remains the same for all the todos,
I have tried every method but no difference pls tell me what's wrong with the code and how do I save the value of the title and description for each todo?
My code:
class _HomePageState extends State<HomePage> {
TextEditingController _titleController = TextEditingController();
TextEditingController _detailController = TextEditingController();
List todos = [];
#override
void initState() {
super.initState();
todos.add('');
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Container(
width: double.infinity,
padding: const EdgeInsets.symmetric(
horizontal: 24.0,
),
color: const Color(0xfff6f6f6f6),
child: Stack(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
margin: const EdgeInsets.only(bottom: 32.0, top: 32.0),
child: const Text(
"Reminders",
style: TextStyle(
fontSize: 25.0,
fontWeight: FontWeight.bold
),
),
),
Expanded(
child: ListView.builder(
itemCount: todos.length,
physics: const BouncingScrollPhysics(),
itemBuilder: (BuildContext context, int index) {
return Dismissible(
key: Key(todos[index]),
child: Container(
width: double.infinity,
padding: const EdgeInsets.symmetric(
vertical: 20.0,
horizontal: 24.0
),
margin: const EdgeInsets.only(
bottom: 20.0,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextField(
cursorColor: Colors.black,
autofocus: true,
controller: _titleController,
style: const TextStyle(
fontSize: 22.0,
fontWeight: FontWeight.bold
),
decoration: const InputDecoration(
hintText: "Enter a title",
border: InputBorder.none,
),
),
const Divider(
color: Colors.black,
),
Padding(
padding: const EdgeInsets.only(top: 0.0),
child: TextField(
controller: _detailController,
style: TextStyle(
fontSize: 20.0,
color: Colors.grey[900],
),
cursorColor: Colors.black,
maxLines: null,
decoration: const InputDecoration(
hintText: "Enter the description",
label: Text("description"),
border: InputBorder.none
),
),
),
],
),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(20.0)
),
),
);
},
),
)
],
),
Positioned(
bottom: 24.0,
right: 0.0,
child: GestureDetector(
onTap: () {
setState(() {
todos.add('');
});
},
child: Container(
width: 60.0,
height: 60.0,
decoration: BoxDecoration(
color: Colors.black87,
borderRadius: BorderRadius.circular(20.0),
),
child: const Icon(Icons.add, color: Colors.white, size: 35.0),
),
),
)
],
),
),
),
);
}
}
Hello and welcome to the world of flutter,
like you do for title and detail, every textfield needs it's own TextEditingController. So you could add a list of controllers for title and description.
List<TextEditingController> _titleController = [];
List<TextEditingController> _detailController = [];
and add an entry to both, when you add todo.
todo.add('')
_titleController.add(TextEditingController())
_detailController.add(TextEditingController())
At the TextFields you should reference by index:
...
child: TextField(controller: _detailController[index],
...
This should help with your problem.
I would recommend you to look at some tutorials and try to rebuild them.
Have fun!

Dismissible container and ListView item not the same size

I just started learning flutter and am trying to build a todo app, the problem I encountered was the Dismissible container and the todo list view item have different heights and after trying everything I still couldn't fix it, the next problem was that the todo item would be dismissed from left to right whereas the container would go up. Any help would be much appreciated. My code:
class _HomePageState extends State<HomePage> {
List todos = [];
List<TextEditingController> _titleController = [];
List<TextEditingController> _detailController = [];
#override
void initState() {
super.initState();
todos.add('');
_titleController.add(TextEditingController());
_detailController.add(TextEditingController());
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Container(
width: double.infinity,
padding: const EdgeInsets.symmetric(
horizontal: 24.0,
),
color: const Color(0xfff6f6f6f6),
child: Stack(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
margin: const EdgeInsets.only(bottom: 32.0, top: 32.0),
child: const Text(
"Reminders",
style: TextStyle(
fontSize: 25.0,
fontWeight: FontWeight.bold
),
),
),
Expanded(
child: ListView.builder(
itemCount: todos.length,
physics: const BouncingScrollPhysics(),
itemBuilder: (BuildContext context, int index) {
return Dismissible(
background: buildActionSwipeLeft(),
onDismissed: (direction) {
setState(() {
todos.removeAt(index);
_titleController.removeAt(index);
_detailController.removeAt(index);
DismissDirection.startToEnd;
});
},
direction: DismissDirection.startToEnd,
key: Key(todos[index]),
child: Padding(
padding: const EdgeInsets.only(
bottom: 15.0
),
child: Card(
color: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
elevation: 4,
child: Container(
width: double.infinity,
padding: const EdgeInsets.symmetric(
vertical: 15.0,
horizontal: 24.0
),
margin: const EdgeInsets.only(
bottom: 20.0,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextField(
cursorColor: Colors.black,
controller: _titleController[index],
style: const TextStyle(
fontSize: 22.0,
fontWeight: FontWeight.bold
),
decoration: const InputDecoration(
hintText: "Enter a title",
border: InputBorder.none,
),
),
const Divider(
color: Colors.black,
),
Padding(
padding: const EdgeInsets.only(top: 0.0),
child: TextField(
controller: _detailController[index],
style: TextStyle(
fontSize: 20.0,
color: Colors.grey[900],
),
cursorColor: Colors.black,
maxLines: null,
decoration: const InputDecoration(
hintText: "Enter the description",
label: Text("description"),
border: InputBorder.none
),
),
),
],
),
),
),
),
);
},
),
)
],
),
Positioned(
bottom: 24.0,
right: 0.0,
child: GestureDetector(
onTap: () {
setState(() {
todos.add('');
_titleController.add(TextEditingController());
_detailController.add(TextEditingController());
});
},
child: Container(
width: 60.0,
height: 60.0,
decoration: BoxDecoration(
color: Colors.black87,
borderRadius: BorderRadius.circular(20.0),
),
child: const Icon(Icons.add, color: Colors.white, size: 35.0),
),
),
)
],
),
),
),
);
}
}
Widget buildActionSwipeLeft() => Container(
alignment: Alignment.centerLeft,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20.0),
color: Colors.red,
),
padding: const EdgeInsets.symmetric(horizontal: 30),
child: const Icon(Icons.delete, color: Colors.white, size: 30),
);
class _HomePageState extends State<HomePage> {
List todos = [];
List<TextEditingController> _titleController = [];
List<TextEditingController> _detailController = [];
#override
void initState() {
super.initState();
todos.add('');
_titleController.add(TextEditingController());
_detailController.add(TextEditingController());
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Container(
width: double.infinity,
padding: const EdgeInsets.symmetric(
horizontal: 24.0,
),
color: const Color(0xfff6f6f6f6),
child: Stack(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
margin: const EdgeInsets.only(bottom: 32.0, top: 32.0),
child: const Text(
"Reminders",
style: TextStyle(
fontSize: 25.0, fontWeight: FontWeight.bold),
),
),
Expanded(
child: ListView.builder(
itemCount: todos.length,
physics: const BouncingScrollPhysics(),
itemBuilder: (BuildContext context, int index) {
return Stack(
clipBehavior: Clip.hardEdge,
children: [
Padding(
padding: const EdgeInsets.only(top:10.0,left: 8.0, right: 8.0),
child: buildActionSwipeLeft(),
),
Dismissible(
onDismissed: (direction) {
setState(() {
todos.removeAt(index);
_titleController.removeAt(index);
_detailController.removeAt(index);
DismissDirection.startToEnd;
});
},
direction: DismissDirection.startToEnd,
key: UniqueKey(),
child: Padding(
padding: const EdgeInsets.only(bottom: 15.0),
child: Card(
color: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
elevation: 4,
child: Container(
width: double.infinity,
padding: const EdgeInsets.symmetric(
vertical: 15.0, horizontal: 24.0),
margin: const EdgeInsets.only(
bottom: 20.0,
),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
TextField(
cursorColor: Colors.black,
controller: _titleController[index],
style: const TextStyle(
fontSize: 22.0,
fontWeight: FontWeight.bold),
decoration: const InputDecoration(
hintText: "Enter a title",
border: InputBorder.none,
),
),
const Divider(
color: Colors.black,
),
Padding(
padding:
const EdgeInsets.only(top: 0.0),
child: TextField(
controller:
_detailController[index],
style: TextStyle(
fontSize: 20.0,
color: Colors.grey[900],
),
cursorColor: Colors.black,
maxLines: null,
decoration: const InputDecoration(
hintText:
"Enter the description",
label: Text("description"),
border: InputBorder.none),
),
),
],
),
),
),
),
)
],
);
},
),
)
],
),
Positioned(
bottom: 24.0,
right: 0.0,
child: GestureDetector(
onTap: () {
setState(() {
todos.add('');
_titleController.add(TextEditingController());
_detailController.add(TextEditingController());
});
},
child: Container(
width: 60.0,
height: 60.0,
decoration: BoxDecoration(
color: Colors.black87,
borderRadius: BorderRadius.circular(20.0),
),
child:
const Icon(Icons.add, color: Colors.white, size: 35.0),
),
),
)
],
),
),
),
);
}
}
Widget buildActionSwipeLeft() => Container(
height: 180,
alignment: Alignment.centerLeft,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20.0),
color: Colors.red,
),
padding: const EdgeInsets.only(left: 30),
child: const Icon(Icons.delete, color: Colors.white, size: 30),
);
Achieving this has a disadvantage of loosing a few animation. Will research more:

Move TextField containing widget to view-able area when keyboard pop up regardless of another widget in the bottom

What am trying to achieve is move my TextField to view-able area when keyboard pop up, also I want a widget(Text widget) that is aligned bottom center to remain in there and get hidden by keyboard.
My Code:
#override
Widget build(BuildContext context) {
//databaseHelper.initializeDatabase();
return Scaffold(
resizeToAvoidBottomPadding: false,
appBar: AppBar(
title: Text('BOM'),
),
body: Builder(builder: (BuildContext context) {
return Container(
child: Stack(children: <Widget>[
//SingleChildScrollView widget tried here, result was a failure
Container(
margin: EdgeInsets.only(bottom: 100.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
margin: EdgeInsets.only(bottom: 50.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
GestureDetector(
onTap: () {
setState(() {
selection = '5-co';
});
},
child: Container(
width: 130.0,
padding: EdgeInsets.all(15.0),
decoration: BoxDecoration(
color: selection == '5-co'
? Colors.green
: Colors.black45,
borderRadius:
BorderRadius.all(Radius.circular(5.0))),
child: Center(
child: Text(
'COMPONENTS',
style: TextStyle(
color: Colors.white,
fontSize: 13.0,
fontWeight: FontWeight.bold),
)),
),
),
Container(
width: 30.0,
),
GestureDetector(
onTap: () {
setState(() {
selection = '5-nl';
});
},
child: Container(
width: 130.0,
padding: EdgeInsets.all(15.0),
decoration: BoxDecoration(
color: selection == '5-nl'
? Colors.blue
: Colors.black45,
borderRadius:
BorderRadius.all(Radius.circular(5.0))),
child: Center(
child: Text(
'REXIN',
style: TextStyle(
color: Colors.white,
fontSize: 13.0,
fontWeight: FontWeight.bold),
)),
),
)
],
),
),
// SizedBox(height: 50,),
Padding(
padding: const EdgeInsets.only(left: 20.0, right: 20.0),
child: TextField(
controller: controller,
decoration: InputDecoration(
labelText: 'Enter article:',
hintText: 'eg: 3290-BR',
prefixIcon: Icon(Icons.local_offer),
suffixIcon: IconButton(
icon: Icon(Icons.search),
onPressed: () {
//if (value.length >= 4) {
navigateToList(controller.text, selection);
// } else
// Scaffold.of(context).showSnackBar(SnackBar(
// content:
//
}),
/*enabledBorder:
OutlineInputBorder(borderRadius: BorderRadius.circular(8.0), borderSide: BorderSide(color: Colors.green)),*/
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0)),
),
onSubmitted: (value) {
//if (value.length >= 4) {
navigateToList(value, selection);
// } else
// Scaffold.of(context).showSnackBar(SnackBar(
// content:
// Text('Oops, please give me more details !')));
},
),
),
]),
),
Align(
alignment: Alignment.bottomCenter,
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Text(' P A N D U',
style: TextStyle(
color: Colors.green,
fontSize: 30.0,
fontWeight: FontWeight.bold)),
))
]));
}));
}
Currently my TextField containing widget is in a container under stack widget and is aligned to center by column widget attribs.
WHAT I TRIED:
I referred some questions in here and tried SingleChildScrollView widget under my stack, and result was my container under the SingleChildScrollView widget loses its column axis attribs and get aligned to top of body.
What I didn't tried to solve my issue is with animations to move widget up. I will go for it if there isn't any other method, cause I gotta learn about those widgets which is still in que. ;')
I made SingleChildScrollView widget under my stack for all my widgets except the bottom wText widget, which I don't want to see when keyboard pops up. And then I just hide my Text widget using flutter's Visibility widget when keyboard comes in screen. This completely solved my problem (I used keyboard_visibility: ^0.5.5 library to get keyboard info, that tells when to hide or show my Text widget in the bottom ).
For reference my unsorted whole code:
bool _visible = true;
#override
void initState() {
super.initState();
KeyboardVisibilityNotification().addNewListener(
onChange: (bool keyvisible) {
//print('keyboard $visible');
setState(() {
_visible = !keyvisible;
});
},
);
}
#override
Widget build(BuildContext context) {
//databaseHelper.initializeDatabase();
return Scaffold(
//resizeToAvoidBottomPadding: false,
appBar: AppBar(
title: Text('BOM'),
),
body: Builder(builder: (BuildContext context) {
return Center(
child: Stack(children: <Widget>[
SingleChildScrollView(
padding: EdgeInsets.all(8.0),
//margin: EdgeInsets.only(bottom: 100.0),
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
SizedBox(
height: 200.0,
),
Container(
margin: EdgeInsets.only(bottom: 50.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
GestureDetector(
onTap: () {
setState(() {
selection = '5-co';
});
},
child: Container(
width: 130.0,
padding: EdgeInsets.all(15.0),
decoration: BoxDecoration(
color: selection == '5-co'
? Colors.green
: Colors.black45,
borderRadius:
BorderRadius.all(Radius.circular(5.0))),
child: Center(
child: Text(
'COMPONENTS',
style: TextStyle(
color: Colors.white,
fontSize: 13.0,
fontWeight: FontWeight.bold),
)),
),
),
Container(
width: 30.0,
),
GestureDetector(
onTap: () {
setState(() {
selection = '5-nl';
});
},
child: Container(
width: 130.0,
padding: EdgeInsets.all(15.0),
decoration: BoxDecoration(
color: selection == '5-nl'
? Colors.blue
: Colors.black45,
borderRadius:
BorderRadius.all(Radius.circular(5.0))),
child: Center(
child: Text(
'REXIN',
style: TextStyle(
color: Colors.white,
fontSize: 13.0,
fontWeight: FontWeight.bold),
)),
),
)
],
),
),
// SizedBox(height: 50,),
Padding(
padding: const EdgeInsets.only(left: 20.0, right: 20.0),
child: TextField(
textInputAction: TextInputAction.search,
controller: controller,
decoration: InputDecoration(
labelText: 'Enter article:',
hintText: 'eg: 3290-BR',
prefixIcon: Icon(Icons.local_offer),
suffixIcon: IconButton(
icon: Icon(Icons.search),
onPressed: () {
//if (value.length >= 4) {
navigateToList(controller.text, selection);
// } else
// Scaffold.of(context).showSnackBar(SnackBar(
// content:
//
}),
/*enabledBorder:
OutlineInputBorder(borderRadius: BorderRadius.circular(8.0), borderSide: BorderSide(color: Colors.green)),*/
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0)),
),
onSubmitted: (value) {
//if (value.length >= 4) {
navigateToList(value, selection);
// } else
// Scaffold.of(context).showSnackBar(SnackBar(
// content:
// Text('Oops, please give me more details !')));
},
),
),
]),
),
),
Align(
alignment: Alignment.bottomCenter,
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Visibility(
visible: _visible,
child: RichText(
text: TextSpan(children: <TextSpan>[
TextSpan(
text: ' P A N D U',
style: TextStyle(
color: Colors.green,
fontSize: 30.0,
fontWeight: FontWeight.bold)),
TextSpan(text: '\t v', style: TextStyle(color: Colors.white70, fontSize: 10.0, fontWeight: FontWeight.bold)),
TextSpan(text: '0.02.05', style: TextStyle(color: Colors.white70, fontSize: 11.0, fontStyle: FontStyle.italic))
])),
),
))
]));
}));
}

How to align a Text to the bottom

I'm trying to build a very simple login page, and i want that the "sign up" text to be at the bottom of the screen.
I'm trying to align the text in the last column to the bottom of the screen, but somehow the aligment doesn't work.
When i try to use the Expanded widget, the IDE throw me an paint error.
class EmailLogin extends StatefulWidget {
#override
_EmailLoginState createState() => _EmailLoginState();
}
class _EmailLoginState extends State<EmailLogin> {
final Map<String, dynamic> _formData = {'email': null, 'password': null};
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
Widget _emailTextField() {
return TextFormField(
decoration: InputDecoration(
labelText: 'Email',
),
keyboardType: TextInputType.emailAddress,
},
onSaved: (String value) {
_formData['email'] = value;
},
);
}
Widget _passwordTextField() {
return TextFormField(
obscureText: true,
validator: (String value) {
if (value.isEmpty || value.length < 6) {
return "please enter valid password";
}
},
onSaved: (String value) {
_formData['password'] = value;
},
decoration: InputDecoration(
labelText: 'Password',
),
);
}
Widget _passwordConfirmTextField() {
return TextFormField(
obscureText: true,
validator: (String value) {
if (value.isEmpty || value.length < 6) {
return "please enter valid password";
}
},
onSaved: (String value) {
_formData['password'] = value;
},
decoration: InputDecoration(
labelText: 'Password',
),
);
}
void _submitForm() {
if (!_formKey.currentState.validate()) {
return;
}
_formKey.currentState.save();
print(_formData);
Navigator.of(context).pushNamed('/home');
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
fit: StackFit.expand,
children: <Widget>[
Image(
image: AssetImage("assets2/car.jpg"),
fit: BoxFit.cover,
color: Colors.black87,
colorBlendMode: BlendMode.darken,
),
SingleChildScrollView(
child: Form(
key: _formKey,
child: Container(
width: double.infinity,
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 80.0),
child: Logo(),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: EdgeInsets.only(top: 8.0, bottom: 80.0),
child: Text(
"Airbnb",
style: TextStyle(fontSize: 30.0),
),
),
],
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20.0),
child: _emailTextField()),
SizedBox(
height: 15.0,
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20.0),
child: _passwordTextField()),
Row(
children: <Widget>[
Expanded(
child: Padding(
padding: const EdgeInsets.only(
left: 20.0, right: 5.0, top: 10.0),
child: GestureDetector(
onTap: () {
_submitForm();
},
child: Container(
alignment: Alignment.center,
height: 60.0,
decoration: BoxDecoration(
color: Color(0xFF18D191),
borderRadius: BorderRadius.circular(10.0)),
child: Text(
'login',
style: TextStyle(
fontSize: 20.0, color: Colors.white),
),
),
),
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.only(
left: 10.0, right: 20.0, top: 10.0),
child: Container(
alignment: Alignment.center,
height: 70.0,
child: Text(
'Forgot Password?',
style: TextStyle(
fontSize: 15.0, color: Color(0xFF18D191)),
),
),
),
),
],
),
Column(
children: <Widget>[
Container(
child: Text("switch to sign up"),
alignment: Alignment.bottomCenter,
),

Run method at page start

I have a Statless widget how to run a function when the widget is loaded or started
How to run _myFunction when the widget is opened?
class Register extends StatelessWidget{
final GlobalKey<ScaffoldState> _registerKey = GlobalKey<ScaffoldState>();
#override
Widget build(BuildContext context) {
return Scaffold(
key: _registerKey,
appBar: new AppBar(
title: new Text('Register'),
centerTitle: true,
),
body: new Center(
child: new Column(
children: <Widget>[
new Container(
margin: const EdgeInsets.only(left: 50, right: 50, top: 20),
child: new TextField(
decoration: InputDecoration(
icon: Icon(Icons.store), hintText: "Store name"),
style: new TextStyle(
fontSize: 20,
color: const Color(0xFF2980b9),
)),
),
new Container(
margin: const EdgeInsets.only(left: 50, right: 50, top: 20),
child: new TextField(
decoration: InputDecoration(
icon: Icon(Icons.person), hintText: "Employee name"),
style: new TextStyle(
fontSize: 20,
color: const Color(0xFF2980b9),
)),
),
new Container(
margin: const EdgeInsets.only(left: 50, right: 50, top: 20),
child: new TextField(
decoration: InputDecoration(
icon: Icon(Icons.email), hintText: "e-mail"),
style: new TextStyle(
fontSize: 20,
color: const Color(0xFF2980b9),
)),
),
new Container(
margin: const EdgeInsets.only(left: 50, right: 50, top: 20),
child: new TextField(
decoration:
InputDecoration(icon: Icon(Icons.phone), hintText: "Phone"),
style: new TextStyle(
fontSize: 20,
color: const Color(0xFF2980b9),
)),
),
new Container(
margin: const EdgeInsets.only(left: 50, right: 50, top: 20),
child: new TextField(
obscureText: true,
decoration: InputDecoration(
icon: Icon(Icons.lock), hintText: "Password"),
style: new TextStyle(
fontSize: 20,
color: const Color(0xFF2980b9),
)),
),
new Container(
margin: const EdgeInsets.only(left: 50, right: 50, top: 20),
child: new TextField(
decoration: InputDecoration(
icon: Icon(Icons.location_on), hintText: "Address"),
style: new TextStyle(
fontSize: 20,
color: const Color(0xFF2980b9),
)),
),
new Container(
margin: const EdgeInsets.only(left: 50, right: 50, top: 20),
child: new Row(
children: <Widget>[
new DropdownButton<String>(
hint: new Text("Choose city"),
items: <String>['A', 'B', 'C', 'D'].map((String value) {
return new DropdownMenuItem<String>(
value: value,
child: new Text(value),
);
}).toList(),
onChanged: (_) {},
),
new DropdownButton<String>(
hint: new Text("Choose area"),
items: <String>['A', 'B', 'C', 'D'].map((String value) {
return new DropdownMenuItem<String>(
value: value,
child: new Text(value),
);
}).toList(),
onChanged: (_) {},
)
],
),
),
new Container(
margin: const EdgeInsets.only(left: 50, right: 50, top: 20),
child: new Container(
child: new RaisedButton(
onPressed: null,
color: const Color(0xFF2980b9),
child: new Row(
mainAxisAlignment: MainAxisAlignment.end,
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
new Text("Register",
style: new TextStyle(
fontSize: 20,
color: const Color(0xFFffffff),
fontFamily: "Roboto")),
new Icon(
Icons.arrow_forward,
color: const Color(0xFFffffff),
),
],
)),
)),
],
)),
);
}
void _myFunction() {
snackBar("Success", _registerKey);
}
}
Use a StatefulWidget and do that inside initState:
class Foo extends StatefulWidget {
#override
_FooState createState() => _FooState();
}
class _FooState extends State<Foo> {
#override
void initState() {
// TODO: call your method
super.initState();
}
#override
Widget build(BuildContext context) {
return Container();
}
}
An alternative is to use hooks
class Foo extends HookWidget {
#override
Widget build(BuildContext context) {
useEffect(() {
// TODO: call your method here
}, const []);
return Container();
}
}