Flutter combo box - dart

I am trying to create a dropdown / combobox widget and having a hard time to figure. Below is the code that I have tried. Basically creating a list that I gathered from here and there but not able to put it in my own code accordingly.
import 'package:flutter/material.dart';
class Signup extends StatefulWidget{
Signup({Key key}) : super (key:key);
final String title;
#override
SignupPage createState() => new SignupPage();
}
class SignupPage extends State<Signup> {
#override
Widget build(BuildContext context) {
List _countrycodes = ["+65","+91"];
List<DropdownMenuItem<String>> _dropDownMenuItems;
String _selectedCountryCode;
List<String> _colors = <String>['', 'red', 'green', 'blue', 'orange'];
String _color = '';
List<DropdownMenuItem<String>> getDropDownMenuItems() {
List<DropdownMenuItem<String>> items = new List();
for (String code in _countrycodes) {
items.add(new DropdownMenuItem(
value: code,
child: new Text(code)
));
}
return items;
}
/**return new Material(
color: Colors.blueAccent,
child: new Scaffold(
body: new Stack(
children: <Widget>[
new Container(
decoration: new BoxDecoration(
image: new DecorationImage(image: new AssetImage("assets/images/download.jpg"), fit: BoxFit.cover,),
),
),
new Center(
child: new Text("Hello LandingPage"),
)
],
)
));**/
final name = TextFormField(
keyboardType: TextInputType.text,
autofocus: false,
initialValue: 'Techie Quickie',
decoration: InputDecoration(
hintText: 'Name',
contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(32.0)
),
),
);
final email = TextFormField(
keyboardType: TextInputType.emailAddress,
autofocus: false,
initialValue: 'tq#gmail.com',
decoration: InputDecoration(
hintText: 'Email',
contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(32.0)
),
),
);
final password = TextFormField(
keyboardType: TextInputType.text,
obscureText: true,
autofocus: false,
initialValue: 'password',
decoration: InputDecoration(
hintText: 'Password',
contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(32.0)
),
),
);
final passwordConfirmation = TextFormField(
keyboardType: TextInputType.text,
obscureText: true,
autofocus: false,
initialValue: 'password',
decoration: InputDecoration(
hintText: 'Password',
contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(32.0)
),
),
);
final loginButton = Padding(
padding: EdgeInsets.symmetric(vertical: 16.0),
child: Material(
borderRadius: BorderRadius.circular(30.0),
shadowColor: Colors.lightBlueAccent.shade100,
elevation: 5.0,
child: MaterialButton(
minWidth: 200.0,
height: 42.0,
onPressed: (){
print("Signup button clicked");
},
color: Colors.lightBlueAccent,
child:
Text('Sign Up',
style: TextStyle(color: Colors.white, fontSize: 20.0),
),
),
)
);
final countryCode = DropdownButton(
value: _selectedCountryCode,
items: _dropDownMenuItems,
onChanged: null
);
final inputDecoratoring =InputDecorator(
decoration: const InputDecoration(
icon: const Icon(Icons.color_lens),
labelText: 'Color',
),
isEmpty: _color == '',
child: new DropdownButtonHideUnderline(
child: new DropdownButton<String>(
value: _color,
isDense: true,
onChanged: (String newValue) {
setState(() {
_color = newValue;
});
},
items: _colors.map((String value) {
return new DropdownMenuItem<String>(
value: value,
child: new Text(value),
);
}).toList(),
),
),
);
return Scaffold(
backgroundColor: Colors.white,
body: Center (
child: ListView(
padding: EdgeInsets.only(left: 24.0, right: 24.0),
shrinkWrap: true,
children: <Widget>[
name,
SizedBox(height: 18.0),
email,
SizedBox(height: 18.0),
password,
SizedBox(height: 18.0),
passwordConfirmation,
SizedBox(height: 18.0),
// countryCode,
// SizedBox(height: 18.0),
loginButton,
SizedBox(height: 38.0),
],
)
)
);
}
}
This is my main.dart class
import 'package:flutter/material.dart';
import 'package:elegal_dart/screens/landing_page.dart';
import 'package:elegal_dart/screens/home.dart';
import 'package:elegal_dart/screens/devices.dart';
import 'package:elegal_dart/screens/signup.dart';
import 'package:elegal_dart/screens/signin.dart';
/*
void main()
{
Devices( new MaterialApp(
home: new Devices(),
));
}*/
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget
{
#override
Widget build(BuildContext context)
{
return new MaterialApp(
title: 'Navigation',
routes: <String, WidgetBuilder>
{
'/Home' : (BuildContext context) => new Home(),
'/LandingPage' : (BuildContext context) => new LandingPage(),
'/Devices' : (BuildContext context) => new Devices(),
'/Signup' : (BuildContext context) => new Signup(),
'/Signin' : (BuildContext context) => new Signin(),
},
//home: new Signin(onSubmit: null),
home: new Signup(),
);
}
}
UPDATED CODE:
import 'package:flutter/material.dart';
class Signup extends StatefulWidget{
Signup({Key key}) : super (key:key);
final String title;
#override
SignupPage createState() => new SignupPage();
}
class SignupPage extends State<Signup> {
#override
Widget build(BuildContext context) {
List _countrycodes = ["+65","+91"];
List<DropdownMenuItem<String>> _dropDownMenuItems;
String _selectedCountryCode;
List<String> _ccodes = <String>['', '+65', '+91', '+60', 'orange'];
String _ccode = '';
List<DropdownMenuItem<String>> getDropDownMenuItems() {
List<DropdownMenuItem<String>> items = new List();
for (String code in _countrycodes) {
items.add(new DropdownMenuItem(
value: code,
child: new Text(code)
));
}
return items;
}
final name = TextFormField(
keyboardType: TextInputType.text,
autofocus: false,
initialValue: 'Techie Quickie',
decoration: InputDecoration(
hintText: 'Name',
contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(32.0)
),
),
);
final email = TextFormField(
keyboardType: TextInputType.emailAddress,
autofocus: false,
initialValue: 'tq#gmail.com',
decoration: InputDecoration(
hintText: 'Email',
contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(32.0)
),
),
);
final password = TextFormField(
keyboardType: TextInputType.text,
obscureText: true,
autofocus: false,
initialValue: 'password',
decoration: InputDecoration(
hintText: 'Password',
contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(32.0)
),
),
);
final passwordConfirmation = TextFormField(
keyboardType: TextInputType.text,
obscureText: true,
autofocus: false,
initialValue: 'password',
decoration: InputDecoration(
hintText: 'Password',
contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(32.0)
),
),
);
final loginButton = Padding(
padding: EdgeInsets.symmetric(vertical: 16.0),
child: Material(
borderRadius: BorderRadius.circular(30.0),
shadowColor: Colors.lightBlueAccent.shade100,
elevation: 5.0,
child: MaterialButton(
minWidth: 200.0,
height: 42.0,
onPressed: (){
print("Signup button clicked");
},
color: Colors.lightBlueAccent,
child:
Text('Sign Up',
style: TextStyle(color: Colors.white, fontSize: 20.0),
),
),
)
);
final countryCode = DropdownButtonHideUnderline (
child: DropdownButton<String>(
value: _ccode,
isDense: true,
items: _ccodes.map((String value) {
return new DropdownMenuItem<String>(
value: value,
child: new Text(value),
);
}).toList(),
onChanged: (String newValue) {
setState(() {
_ccode = newValue;
});
}
)
);
return Scaffold(
backgroundColor: Colors.white,
body: Center (
child: ListView(
padding: EdgeInsets.only(left: 24.0, right: 24.0),
shrinkWrap: true,
children: <Widget>[
name,
SizedBox(height: 18.0),
email,
SizedBox(height: 18.0),
password,
SizedBox(height: 18.0),
passwordConfirmation,
SizedBox(height: 18.0),
countryCode,
SizedBox(height: 18.0),
loginButton,
SizedBox(height: 38.0),
],
)
)
);
}
}
The error that I am getting in the AVD

The assertion tells you that items must not be null. It's referring to this one: items: _dropDownMenuItems,. You don't ever assign _dropDownMenuItems.
This is a good use for a Dart-y pattern. Replace it with:
final countryCode = DropdownButton(
value: _selectedCountryCode,
items: _countrycodes
.map((code) =>
new DropdownMenuItem(value: code, child: new Text(code)))
.toList(),
onChanged: null,
);
and you no longer need the field or the getDropDownMenuItems function. If you aren't familiar with this syntax, read it as "map each code in countryCodes to a DropdownMenuItem and form them back into a List"
Also, the scope of your variables is wrong. Move them out of the build function and into the State, like this:
class SignupPage extends State<Signup> {
List<String> _countrycodes = ["+65", "+91"];
List<String> _colors = ['', 'red', 'green', 'blue', 'orange'];
String _selectedCountryCode;
String _color = '';

My answer will solve also the problem of using more than one DropdownButton in the same page without the error of more than 1 item in the DropdownMenuItem .
First define the lists you will use this way:
static const List<String> _razas = const
["Schnauzer", "Ovejero Alemán", "Husky", "Brasov",
"Constanta","Mestizo"];
////////barrios
static const List<String> _barrios = const
"Belgrano", "Caballito", "Colegiales", "Lugano", "Palermo","Pilar",
"Montserrat", "Vicente López" ];
static const List<String> _tamanio = const
["Chico", "Mediano", "Grande" ];
String tamanioValue = _tamanio[0];
String barriosValue = _barrios[0];
String razasValue = _razas[0];
Then use this Containers in your Scaffold
Container(
margin: EdgeInsets.only(top:20.0, bottom: 20.0),
child: new Row(
mainAxisAlignment: MainAxisAlignment.start,
children:<Widget> [
Text("RAZA "),
new DropdownButton(value:razasValue,
onChanged: (string) => setState(() => razasValue =
string),
items: _razas.map((string) {
return new DropdownMenuItem(
child: new Text(string),
value: string,
);
}).toList(),
),
]
)
),
Container(
margin: EdgeInsets.only(top:20.0, bottom: 20.0),
child: new Row(
mainAxisAlignment: MainAxisAlignment.start,
children:<Widget> [
Text("BARRIO "),
new DropdownButton(value:barriosValue,
onChanged: (string) => setState(() =>
barriosValue = string),
items: _barrios.map((string) {
return new DropdownMenuItem(
child: new Text(string),
value: string,
);
}).toList(),
),
]
)
),
Then just replace the values for you database or any file you store the data
raza: razasValue,
barrio: barriosValue,

Related

unable to display snackbar in flutter

I am very new to flutter and stuck on the point of displaying a SnackBar when login fails .Kindly check the code below and let me know how to fix this problem. I don't know where exactly do I need to have builder. You can suggest to me the best solution to display SnackBar in a simple and quick way. Many thanks in advance to all those who will help.
class LoginPage extends StatefulWidget {
static String tag = 'login-page';
#override
_LoginPageState createState() => new _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
bool passwordVisible = true;
var _scaffoldKey = new GlobalKey<ScaffoldState>();
#override
Widget build(BuildContext context) {
final logo = Hero(
tag: 'hero',
child: CircleAvatar(
backgroundColor: Colors.transparent,
radius: 48.0,
child: Image.asset('assets/splash.png'),
),
);
/* final email = TextFormField(
keyboardType: TextInputType.emailAddress,
autofocus: false,
initialValue: 'mufeez#gmail.com',
decoration: InputDecoration(
hintText: 'Email',
contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
border: OutlineInputBorder(borderRadius: BorderRadius.circular(32.0)),
),
);
*/
final password = TextFormField(
autofocus: false,
obscureText: passwordVisible,//This will obscure text dynamically
decoration: InputDecoration(
hintText: 'Enter Secret Key',
contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
border: OutlineInputBorder(borderRadius: BorderRadius.circular(32.0)),
suffixIcon: IconButton(
icon: Icon(
// Based on passwordVisible state choose the icon
passwordVisible
? Icons.visibility_off
: Icons.visibility,
color: Theme.of(context).primaryColorDark,
),
onPressed: () {
// Update the state i.e. toogle the state of passwordVisible variable
setState(() {
passwordVisible
? passwordVisible = false
: passwordVisible = true;
});
},
),
),
);
final loginButton = Padding(
padding: EdgeInsets.symmetric(vertical: 16.0),
child: RaisedButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(24),
),
onPressed: () async {
final snackBar = SnackBar(content: Text('Yay! A SnackBar!'));
Scaffold.of(context).showSnackBar(snackBar);
},
padding: EdgeInsets.all(12),
color: Colors.lightBlueAccent,
child: Text('Log In', style: TextStyle(color: Colors.white)),
),
);
/* final forgotLabel = FlatButton(
child: Text(
'Forgot password?',
style: TextStyle(color: Colors.black54),
),
onPressed: () {},
);
*/
return Scaffold(
backgroundColor: Colors.white,
body: Center(
child: ListView(
shrinkWrap: true,
padding: EdgeInsets.only(left: 24.0, right: 24.0),
children: <Widget>[
logo,
SizedBox(height: 48.0),
SizedBox(height: 8.0),
password,
SizedBox(height: 24.0),
loginButton,
],
),
),
);
}
you have to use scaffold key to do so.
what you have to add in scaffold widget.
return Scaffold(
key: _scaffoldKey,
backgroundColor: Colors.white,
and at the time of display snackbar you have to use scaffold key.
replace your onPressed with below code.
onPressed: () async {
final snackBar = SnackBar(content: Text('Yay! A SnackBar!'));
_scaffoldKey.currentState.showSnackBar(snackBar);
},
You can also wrap your Scaffold body in a Builder() widget.
return Scaffold(
body: body: Builder(
builder: (BuildContext ctxt) {
return (your content here);}));
and when want to display the Snackbar juste use Scaffold.of(ctxt) onPressed
onPressed: () {
Scaffold.of(ctxt).showSnackBar(
SnackBar(content:Text('My snack')));
},

Flutter code, accept value from user display required field

**Hello, I am developing an app in which the user should enter the integer values.according to that values we should display those number of text fields..
for Example:
1) enter total number of subject=10;
2) click on the button;
3) After button is clicked should display 10 text fields;
4) I have no idea what to do so if you know then help me plz.**
import 'package:flutter/material.dart';
class imcaaddsubject extends StatefulWidget {
#override
_imcaaddsubjectState createState() => _imcaaddsubjectState();
}
class _imcaaddsubjectState extends State<imcaaddsubject> {
#override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(5),
child: Card(
child: ListView(
padding: EdgeInsets.all(10),
children: <Widget>[
Padding(
padding: EdgeInsets.only(top: 10),
),
new TextField(
decoration: InputDecoration(
border: OutlineInputBorder(
borderSide: BorderSide(style: BorderStyle.solid)),
labelText: "NUMBER OF SUBJECTS",
hintText: "Enter number of subjects",
),keyboardType: TextInputType.number,
),
Padding(
padding: EdgeInsets.only(top: 15),
),
new RaisedButton(
child: Text(
"OK",
style:
TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
),
color: Colors.cyan,
onPressed: () {},
)
],
),
),
);
}
}
You can try like this :
import 'package:flutter/material.dart';
void main() => runApp(MaterialApp(
home: MyApp(),
));
class MyApp extends StatefulWidget {
#override
MyAppState createState() => MyAppState();
}
class MyAppState extends State<MyApp> {
int numberOfSubjects = 0;
Widget subjectsBuilder(int numberOfSubjects) {
if (numberOfSubjects > 0) {
return ListView.builder(
itemBuilder: (BuildContext context, numberOfSubjects) {
return TextField(
decoration: InputDecoration(hintText: "enter a text"),
);
},
itemCount: numberOfSubjects,
);
} else {
return SizedBox();
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(children: <Widget>[
Expanded(
child: Container(
padding: EdgeInsets.all(5),
child: Card(
child: ListView(
padding: EdgeInsets.all(10),
children: <Widget>[
Padding(
padding: EdgeInsets.only(top: 10),
),
new TextField(
onSubmitted: (String value) {
setState(() {
numberOfSubjects = int.parse(value);
});
},
decoration: InputDecoration(
border: OutlineInputBorder(
borderSide: BorderSide(style: BorderStyle.solid)),
labelText: "NUMBER OF SUBJECTS",
hintText: "Enter number of subjects",
),
keyboardType: TextInputType.number,
),
Padding(
padding: EdgeInsets.only(top: 15),
),
],
),
),
),
),
Expanded(
child: subjectsBuilder(numberOfSubjects),
)
]),
);
}
}
this code will display a number of text fields according to user input below the first text field , of course you can render it in a new page .. also you don't have to use a button , it's enough to user submit text .

Can´t show snackbar in flutter login

Im creating a login form in flutter and I want to use snackbar to show a message when login fails. I read this documentation and if i have this code should works
final snackBar = SnackBar(content: Text('Yay! A SnackBar!'));
Scaffold.of(context).showSnackBar(snackBar);
But return this error
Scaffold.of() called with a context that does not contain a Scaffold.
My login.dart all code
import 'package:flutter/material.dart';
import 'package:fluttercrud/screens/home_page.dart';
class LoginPage extends StatelessWidget {
static String tag = 'login-page';
#override
Widget build(BuildContext context) {
final logo = Hero(
tag: 'hero',
child: CircleAvatar(
backgroundColor: Colors.transparent,
radius: 48.0,
child: Image.asset('assets/logo.png'),
),
);
final email = TextFormField(
keyboardType: TextInputType.emailAddress,
autofocus: false,
decoration: InputDecoration(
hintText: 'Usuario',
contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
border: OutlineInputBorder(borderRadius: BorderRadius.circular(32.0)),
),
);
final password = TextFormField(
autofocus: false,
obscureText: true,
decoration: InputDecoration(
hintText: 'Contraseña',
contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
border: OutlineInputBorder(borderRadius: BorderRadius.circular(32.0)),
),
);
final loginButton = Padding(
padding: EdgeInsets.symmetric(vertical: 16.0),
child: Material(
borderRadius: BorderRadius.circular(30.0),
child: MaterialButton(
minWidth: 200.0,
height: 42.0,
onPressed: () {
final snackBar = SnackBar(content: Text('Yay! A SnackBar!'));
Scaffold.of(context).showSnackBar(snackBar);
//Navigator.of(context).pushNamed(HomePage.tag);
},
color: Colors.blue[300],
child: Text('Entrar', style: TextStyle(color: Colors.white)),
),
),
);
final forgotLabel = FlatButton(
child: Text(
'¿Contraseña olvidada?',
style: TextStyle(color: Colors.black),
),
onPressed: () {},
);
return Scaffold(
backgroundColor: Colors.white,
body: Center(
child: ListView(
shrinkWrap: true,
padding: EdgeInsets.only(left: 24.0, right: 24.0),
children: <Widget>[
logo,
SizedBox(height: 48.0),
email,
SizedBox(height: 8.0),
password,
SizedBox(height: 24.0),
loginButton,
forgotLabel
],
),
),
);
}
}
The scaffold return a error but i don´t know how can i fix this without rewrite all code.
So the question is: How can i to show the snackbar when login fails and avoid this error? And why this error appears?
UPDATED
void initState() {
super.initState();
final snackBar = SnackBar(
content: Text(
'Usuario/Contraseña incorrecto',
textAlign: TextAlign.center,
));
Scaffold.of(context).showSnackBar(snackBar);
seriesList = _createSampleData();
animate = false;
}
And how can i show snackbar when init page?
This is because you are using the context of the widget that creates the Scaffold (the parent context), not the context of the Scaffold itself. Thus the error.
You can fix the error either by creating a method builder that will receive the correct context:
Widget _buildLoginButton(BuildContext context) {
return Padding(
padding: EdgeInsets.symmetric(vertical: 16.0),
child: Material(
borderRadius: BorderRadius.circular(30.0),
child: MaterialButton(
minWidth: 200.0,
height: 42.0,
onPressed: () {
final snackBar = SnackBar(content: Text('Yay! A SnackBar!'));
Scaffold.of(context).showSnackBar(snackBar);
},
color: Colors.blue[300],
child: Text('Entrar', style: TextStyle(color: Colors.white)),
),
),
);
}
And refactor the page to use the builder method you've just created:
Scaffold(
appBar: AppBar(
title: Text('My Page'),
),
body: Builder(
builder: (context) =>
Column(
children: [
.....
_buildLoginButton(context),
.....
]
),
),
),
);
Or just extract the login button to its own Widget, without changing any other of your code, and it will receive the proper context.
class LoginButton extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.symmetric(vertical: 16.0),
child: Material(
borderRadius: BorderRadius.circular(30.0),
child: MaterialButton(
minWidth: 200.0,
height: 42.0,
onPressed: () {
final snackBar = SnackBar(content: Text('Yay! A SnackBar!'));
Scaffold.of(context).showSnackBar(snackBar);
},
color: Colors.blue[300],
child: Text('Entrar', style: TextStyle(color: Colors.white)),
),
),
);
}
}

Make two widgets side by side

I have the below code and I want the country code and phone number side by side, how to get that? I have tried multiple examples, sometimes it disappears totally and sometimes crashes. I have the below code and I want the country code and phone number side by side, how to get that? I have tried multiple examples, sometimes it disappears totally and sometimes crashes.
import 'package:flutter/material.dart';
class Signup extends StatefulWidget{
Signup({Key key}) : super (key:key);
final String title;
#override
SignupPage createState() => new SignupPage();
}
class SignupPage extends State<Signup> {
List<String> _ccodes = <String>['', '+65', '+91', '+60', '+61'];
String _ccode = '';
#override
Widget build(BuildContext context) {
final name = TextFormField(
keyboardType: TextInputType.text,
autofocus: false,
initialValue: 'Techie Quickie',
decoration: InputDecoration(
hintText: 'Name',
contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(32.0)
),
),
);
final email = TextFormField(
keyboardType: TextInputType.emailAddress,
autofocus: false,
initialValue: 'tq#gmail.com',
decoration: InputDecoration(
hintText: 'Email',
contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(32.0)
),
),
);
final password = TextFormField(
keyboardType: TextInputType.text,
obscureText: true,
autofocus: false,
initialValue: 'password',
decoration: InputDecoration(
hintText: 'Password',
contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(32.0)
),
),
);
final passwordConfirmation = TextFormField(
keyboardType: TextInputType.text,
obscureText: true,
autofocus: false,
initialValue: 'password',
decoration: InputDecoration(
hintText: 'Password',
contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(32.0)
),
),
);
final loginButton = Padding(
padding: EdgeInsets.symmetric(vertical: 16.0),
child: Material(
borderRadius: BorderRadius.circular(30.0),
shadowColor: Colors.lightBlueAccent.shade100,
elevation: 5.0,
child: MaterialButton(
minWidth: 200.0,
height: 42.0,
onPressed: (){
print("Signup button clicked");
},
color: Colors.lightBlueAccent,
child:
Text('Sign Up',
style: TextStyle(color: Colors.white, fontSize: 20.0),
),
),
)
);
final countryCode = DropdownButton<String>(
value: _ccode,
isDense: true,
items: _ccodes.map((String value) {
return new DropdownMenuItem<String>(
value: value,
child: new Text(value),
);
}).toList(),
onChanged: (String newValue) {
setState(() {
_ccode = newValue;
});
}
)
;
final phonenumber = TextFormField(
keyboardType: TextInputType.phone,
autofocus: false,
initialValue: '91166666',
decoration: InputDecoration(
hintText: 'Phone Number',
contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(32.0)
),
),
);
return Scaffold(
backgroundColor: Colors.white,
body: Center (
child: ListView(
padding: EdgeInsets.only(left: 24.0, right: 24.0),
shrinkWrap: true,
children: <Widget>[
name,
SizedBox(height: 18.0),
email,
SizedBox(height: 18.0),
password,
SizedBox(height: 18.0),
passwordConfirmation,
SizedBox(height: 18.0),
Row(
children: [
new Expanded(
child: new Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
countryCode,
SizedBox(height: 18.0),
],
),
),
],
),
phonenumber,
SizedBox(height: 18.0),
loginButton,
SizedBox(height: 38.0),
],
)
)
);
}
}
Try checking this URL : https://flutter.io/tutorials/layout/
You can have different rows in your body to have adjacent components.
So the heirarchy would be like
Body
Container
Row{
Child: (item1)
Child(item2)}
Hope this helps. :)
The problem is related to way TextField gets rendered and their dimensions. You can find more details in this question and this issue.
Anyway this code should work:
import 'package:flutter/material.dart';
void main() {
runApp(new MaterialApp(
title: 'My app', // used by the OS task switcher
home: new Signup(),
));
}
class Signup extends StatefulWidget {
Signup({Key key}) : super(key: key);
final String title;
#override
SignupPage createState() => new SignupPage();
}
class SignupPage extends State<Signup> {
List<String> _ccodes = <String>['', '+65', '+91', '+60', '+61'];
String _ccode = '';
#override
Widget build(BuildContext context) {
final name = TextFormField(
keyboardType: TextInputType.text,
autofocus: false,
initialValue: 'Techie Quickie',
decoration: InputDecoration(
hintText: 'Name',
contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
border: OutlineInputBorder(borderRadius: BorderRadius.circular(32.0)),
),
);
final email = TextFormField(
keyboardType: TextInputType.emailAddress,
autofocus: false,
initialValue: 'tq#gmail.com',
decoration: InputDecoration(
hintText: 'Email',
contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
border: OutlineInputBorder(borderRadius: BorderRadius.circular(32.0)),
),
);
final password = TextFormField(
keyboardType: TextInputType.text,
obscureText: true,
autofocus: false,
initialValue: 'password',
decoration: InputDecoration(
hintText: 'Password',
contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
border: OutlineInputBorder(borderRadius: BorderRadius.circular(32.0)),
),
);
final passwordConfirmation = TextFormField(
keyboardType: TextInputType.text,
obscureText: true,
autofocus: false,
initialValue: 'password',
decoration: InputDecoration(
hintText: 'Password',
contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
border: OutlineInputBorder(borderRadius: BorderRadius.circular(32.0)),
),
);
final loginButton = Padding(
padding: EdgeInsets.symmetric(vertical: 16.0),
child: Material(
borderRadius: BorderRadius.circular(30.0),
shadowColor: Colors.lightBlueAccent.shade100,
elevation: 5.0,
child: MaterialButton(
minWidth: 200.0,
height: 42.0,
onPressed: () {
print("Signup button clicked");
},
color: Colors.lightBlueAccent,
child: Text(
'Sign Up',
style: TextStyle(color: Colors.white, fontSize: 20.0),
),
),
));
final countryCode = DropdownButton<String>(
value: _ccode,
isDense: true,
items: _ccodes.map((String value) {
return new DropdownMenuItem<String>(
value: value,
child: new Text(value),
);
}).toList(),
onChanged: (String newValue) {
setState(() {
_ccode = newValue;
});
});
final phonenumber = TextFormField(
keyboardType: TextInputType.phone,
autofocus: false,
initialValue: '91166666',
decoration: InputDecoration(
hintText: 'Phone Number',
contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
border: OutlineInputBorder(borderRadius: BorderRadius.circular(32.0)),
),
);
return Scaffold(
backgroundColor: Colors.white,
body: Center(
child: ListView(
padding: EdgeInsets.only(left: 24.0, right: 24.0),
shrinkWrap: true,
children: <Widget>[
name,
SizedBox(height: 18.0),
email,
SizedBox(height: 18.0),
password,
SizedBox(height: 18.0),
passwordConfirmation,
SizedBox(height: 18.0),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
countryCode,
new Flexible(child: phonenumber),
],
),
SizedBox(height: 18.0),
loginButton,
SizedBox(height: 38.0),
],
)));
}
}

TextFormField value not updating as intended in flutter

I have a strange problem in my application I have a signup page with several textformfields inside a ListView and the ListView is a child to the Form.
when i reach the last formfield inside the ListView i need to scroll up the screen to actually see what i am typing inside the field. When i do scroll up the textformfields which go out of focus are losing the entered text and are initialised as null. I am not sure what i am missing or do i have to use some other way to make sure i retain the TextFormField values. I have tried to use the controller in every TextFormField then it is retaining the value even if I scroll up. But, the properties of the object e.g, hostelData.hostelName are only updated first time and the changes are not reflected in the object property from the second time. I am not so sure what i am missing? Please can someone help me in solving this.
Please excuse my mistakes in posting as i am new to programming and any help would be greatly appreciated.
I have posted the code below so that you can reproduce the same problem.
import 'dart:async';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
import 'package:myhostel/theme.dart' as Theme;
import 'package:myhostel/globals.dart' as gl;
class SignUp extends StatefulWidget {
const SignUp({ Key key }) : super(key: key);
#override
_SignUpState createState() => new _SignUpState();
}
class HostelData{
String hostelName = '';
String ownersName = '';
String mobileNumber = '';
String emailId = '';
String password = '';
String city = '';
String hostelType= 'mens';
String confirmPassword ='';
}
class _SignUpState extends State<SignUp> {
HostelData hostelData = new HostelData();
void showInSnackBar(String value) {
_scaffoldKey.currentState.showSnackBar(new SnackBar(
content: new Text(value),
duration: const Duration(milliseconds: 3000),
));
}
final GlobalKey<FormState> _formKey = new GlobalKey<FormState>();
final GlobalKey<FormFieldState<String>> _passwordFieldKey = new
GlobalKey<FormFieldState<String>>();
bool _autovalidate = false;
bool _formWasEdited = false;
void _handleSubmitted() {
final FormState form = _formKey.currentState;
if (!form.validate()) {
_autovalidate = true; // Start validating on every change.
showInSnackBar('Please fix the errors in red before submitting.');
} else {
form.save();
showInSnackBar('${hostelData.ownersName}\'s hostel name is
${hostelData.hostelName}');
_createuserwithemailandpassword();
}
}
String _validateName(String value) {
_formWasEdited = true;
if (value.isEmpty)
return 'Name is required.';
final RegExp nameExp = new RegExp(r'^[A-Za-z ]+$');
if (!nameExp.hasMatch(value))
return 'Please enter only alphabetical characters and spaces.';
return null;
}
String _validatePassword(String value) {
_formWasEdited = true;
final FormFieldState<String> passwordField =
_passwordFieldKey.currentState;
if (passwordField.value == null || passwordField.value.isEmpty)
return 'Please choose a password.';
if (passwordField.value != value)
return 'Passwords don\'t match';
return null;
}
#override
Widget build(BuildContext context){
return new MaterialApp(
theme: Theme.MyHostelThemeData,
home: new Scaffold(
key: _scaffoldKey,
body: new Container(
child: new Container(
decoration: new BoxDecoration(
image: new DecorationImage(
image: new AssetImage('assets/bg.png'),
fit: BoxFit.fill,
),
),
child: new Form(
key: _formKey,
autovalidate: _autovalidate,
child: new ListView(
children: <Widget>[
new Container(
margin: const EdgeInsets.only(top:32.0),
child: new Center(
child: new Text('SIGN UP',
style: new TextStyle(
color: const Color(0xFFF5FEFD),fontSize:24.0,fontWeight:
FontWeight.bold),
),
),
),
new Row(
children:[
new Expanded(
child: new Container(
margin: const EdgeInsets.only(left: 24.0,right: 12.0,),
child:new TextFormField(decoration: new InputDecoration(
/*hintStyle: new TextStyle(
fontSize: 20.0,color: const Color(0xFFF5FEFD),),*/
labelText: 'Hostel Name',
),
/*style: new TextStyle(
fontSize: 20.0,
color: Colors.white,
),*/
onSaved:(String value){ hostelData.hostelName = value; },
validator: _validateName,
),
),
),
],
),
new Row(
children:[
/*new Container(
margin: const EdgeInsets.all(8.0),
width: 24.0,
child: new Image.asset(
'assets/person_avatar.png',
fit: BoxFit.contain,
//alignment: FractionalOffset.center,
),
),*/
new Expanded(
child: new Container(
margin: const EdgeInsets.only(left: 24.0,right: 12.0,),
child:new TextFormField(
//controller: _ownersNameController,
decoration: new InputDecoration(//hintText: 'Mobile
Number',
/* hintStyle: new TextStyle(fontSize: 20.0,color: const
Color(0xFFF5FEFD),),*/
labelText: 'Owners Name',
),
/*style: new TextStyle(
fontSize: 20.0,
color: Colors.white,
),*/
onSaved: (String value) { hostelData.ownersName = value;
},
validator: _validateName,
),
),
),
],
),
new Row(
children:[
new Expanded(
child: new Container(
margin: const EdgeInsets.only(left: 24.0,right: 12.0,),
child:new TextFormField(
//controller: _mobileNumberController,
keyboardType: TextInputType.phone,
decoration: new InputDecoration(//hintText: 'Mobile
Number',
/* hintStyle: new TextStyle(fontSize: 20.0,color:
const Color(0xFFF5FEFD),),*/
labelText: 'Mobile Number',
//prefixText: '+91',
),
/*style: new TextStyle(
fontSize: 20.0,
color: Colors.white,
),*/
onSaved: (String value) { hostelData.mobileNumber = value; },
//validator: _validatePhoneNumber,
),
),
),
],
),
//implements EmailID Row
new Row(
children:[
new Expanded(
child: new Container(
margin: const EdgeInsets.only(left: 24.0,right: 12.0,),
child:new TextFormField(
//controller: _emailIdController,
decoration: new InputDecoration(
//hintText: 'Mobile Number',
/*hintStyle: new TextStyle(fontSize: 20.0,color: const
Color(0xFFF5FEFD),),*/
labelText: 'EMail Id',
helperText: 'Required',
),
/*style: new TextStyle(
fontSize: 20.0,
color: Colors.white,
),*/
onSaved: (String value){hostelData.emailId = value;},
),
),
),
],
),
//implements the password row
new Container(
padding: const EdgeInsets.only(left: 8.0,),
child: new Row(
children: <Widget>[
new Container(
margin: const EdgeInsets.only(top: 16.0),
//padding: const EdgeInsets.all(8.0),
child: new Icon(Icons.lock_outline,
color: const Color(0xFFF5FEFD)
),
),
new Expanded(
child: new Container(
margin: const EdgeInsets.only(
left: 28.0, right: 12.0,),
child: new TextFormField(
key: _passwordFieldKey,
//controller: _passwordController,
decoration: const InputDecoration(
hintText: 'min 8 characters',
labelText: 'Password',
helperText: 'Required',
),
autocorrect: false,
//obscureText: true,
//validator: 'Required',
/*style: DefaultTextStyle.of(context).style.merge(new
TextStyle(
fontSize: 16.0,
color: CustomColors.fontColor,
),
),*/
onSaved: (String value){hostelData.password = value;},
),
),
),
],
),
),
new Container(
padding: const EdgeInsets.only(left: 8.0,),
child: new Row(
children: <Widget>[
new Container(
margin: const EdgeInsets.only(top: 16.0),
//padding: const EdgeInsets.all(8.0),
child: new Icon(Icons.lock_outline,
color: const Color(0xFFF5FEFD)
),
),
new Expanded(
child: new Container(
margin: const EdgeInsets.only(
left: 28.0, right: 12.0,),
child: new TextFormField(
//controller: _confirmpasswordcontroller,
decoration: const InputDecoration(
labelText: 'Confirm Password',
helperText: 'Required'
),
autocorrect: false,
// obscureText: true,
//validator: 'Required',
/*style: DefaultTextStyle.of(context).style.merge(new
TextStyle(
fontSize: 16.0,
color: CustomColors.fontColor,
),
),*/
//onSaved: (String value){hostelData.confirmPassword =
value;},
validator: _validatePassword,
),
),
),
],
),
),
new Row(
children:[
new Expanded(
child: new Container(
margin: const EdgeInsets.only(left: 24.0,right: 12.0,),
child:new TextFormField(
controller: _cityController,
decoration: new InputDecoration(labelText: 'City*'),
onSaved: (String value){hostelData.city = value;},
validator: _validateName,
),
),
),
],
),
new Container(
padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.only(left:24.0,right: 24.0),
decoration: new BoxDecoration(
border: new Border.all(
color: Colors.white,
width: 2.0,
),
borderRadius: new BorderRadius.all(const
Radius.circular(32.0),)
),
child: new FlatButton(
onPressed: ((){
print('SignUp Button Clicked');
_handleSubmitted();
}),
child: new Text (
'SIGN UP',
style: new TextStyle(fontSize: 24.0,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
),
),
new Row(
children:[
new Container(
margin: const EdgeInsets.only(left: 24.0,bottom: 12.0),
child:new Text(
'Already have an account?',
style: new TextStyle(
fontSize: 20.0,
color: Colors.white,
),
),
),
new Container(
padding: const EdgeInsets.only(right: 8.0,top:
4.0,bottom:16.0),
margin: const EdgeInsets.only(right: 12.0,left: 4.0),
child:
new MaterialButton(
onPressed: ((){
//Sign In Button pressed declaration here
print('sign in button clicked');
}),
child: new Text('SignIn',
style: new TextStyle(
fontSize: 16.0,
color: Colors.teal[200],
),
),
minWidth: 16.0,
),
),
],
),
new Container(
padding: const EdgeInsets.only(left: 16.0),
child: new Text('* indicates required field',
style: new TextStyle(
fontSize: 14.0,
color: Colors.white,
),),
),
]
),
),
),
),
),
);
} // widget ends here
globals.dart
library my_hostel.globals;
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_database/firebase_database.dart';
final FirebaseAuth auth = FirebaseAuth.instance;
final DatabaseReference messagesRef =FirebaseDatabase.instance.reference();
Here is an example of working code:
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String s1 = "";
String s2 = "";
String s3 = "";
String s4 = "";
String s5 = "";
final TextEditingController c1 = new TextEditingController();
final TextEditingController c2 = new TextEditingController();
final TextEditingController c3 = new TextEditingController();
final TextEditingController c4 = new TextEditingController();
final TextEditingController c5 = new TextEditingController();
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(title: new Text("Example"),),
body: new ListView(
children: <Widget>[
new Padding(padding: new EdgeInsets.all(70.0),),
new TextField(
controller: c1,
onChanged: (String text) {
s1 = text;
},
),
new Padding(padding: new EdgeInsets.all(70.0),),
new TextField(
controller: c2,
onChanged: (String text) {
s2 = text;
},
),
new Padding(padding: new EdgeInsets.all(70.0),),
new TextField(
controller: c3,
onChanged: (String text) {
s3 = text;
},
),
new Padding(padding: new EdgeInsets.all(70.0),),
new TextField(
controller: c4,
onChanged: (String text) {
s4 = text;
},
),
new Padding(padding: new EdgeInsets.all(70.0),),
new TextField(
controller: c5,
onChanged: (String text) {
s5 = text;
},
),
],
)
);
}
}
You need to add a TextEditingController with your TextField. Listview removes invisible widgets because rendering a ton of widgets that are not being displayed would make it perform worse!

Resources