I am trying to validate two TextFormFields (Email and Password) in my project. But i get an exception while to validate the TextFormField. Can someone let me know where i went wrong? Or how the error can be fixed.
The error i get is : ════════ Exception caught by gesture ═══════════════════════════════════════════ Null check operator used on a null value ════════════════════════════════════════════════════════════════════════════════
My Code :
class _LoginState extends State<Login> {
#override
Widget build(BuildContext context) {
final _formKey = GlobalKey<FormState>();
TextEditingController emailController;
TextEditingController passwordController;
final authService = Provider.of<AuthService>(context);
emailController = TextEditingController();
passwordController = TextEditingController();
return Scaffold(
backgroundColor: Colors.white,
body: SingleChildScrollView(
child: Column(children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 60.0),
child: Center(
child: Container(
width: 300,
height: 380,
decoration:
BoxDecoration(borderRadius: BorderRadius.circular(50.0)),
child: Image.asset(
'assets/images/logo.png',
)),
),
),
const SizedBox(height: 15.0),
Padding(
padding: EdgeInsets.only(left: 25.0, right: 25.0, top: 0, bottom: 0),
child: TextFormField(
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter the email.';
}
return null;
},
controller: emailController,
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(60),
),
prefixIcon: const Icon(Icons.mail),
labelText: 'E-Mail',
hintText: 'admin#gmail.com'),
),
),
Padding(
padding: EdgeInsets.only(left: 25.0, right: 25.0, top: 15, bottom: 0),
child: TextFormField(
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter the password.';
}
return null;
},
controller: passwordController,
obscureText: true,
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(60),
),
prefixIcon: const Icon(Icons.vpn_key),
labelText: 'Password',
hintText: 'Enter your Password'),
),
),
const SizedBox(
height: 100,
),
TextButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Processing')),
);
}
authService.signInWithEmailAndPassword(context,
emailController.text.trim(), passwordController.text.trim());
},
child: const Text(
'Login',
textAlign: TextAlign.center,
)),
MaterialButton(
onPressed: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => forgotPassword()));
},
child: Text(
'Forgot Password',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 13.0, color: Colors.red.shade900),
))
])),
);
}
}
Thank you in advance.
There is no Form widget used _formKey in your snippet, that's why it is throwing errors from _formKey.currentState!.validate(). Because you are using ! that says currentState of formKey will never get null.
You can do handle it by check null state first.
TextButton(
onPressed: () {
if (_formKey.currentState == null) {
return; // dont execute rest code
}
if (_formKey.currentState!.validate()) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Processing')),
);
authService.signInWithEmailAndPassword(context,
emailController.text.trim(),
passwordController.text.trim());
},
Place Form widget before Column widget.
body: SingleChildScrollView(
child: Form(
key: _formKey,
child: Column(children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 60.0),
child: Center(
More about forms validation
You are causing this error because you have defined a _formkey but not used it in your code so it doesn't have any value or State right now you have to wrap your TextFormField in Form widget and need to pass the defined key, you can check in the code below
final _formKey = GlobalKey<FormState>();
class _LoginState extends State<Login> {
#override
Widget build(BuildContext context) {
TextEditingController emailController;
TextEditingController passwordController;
final authService = Provider.of<AuthService>(context);
emailController = TextEditingController();
passwordController = TextEditingController();
return Scaffold(
backgroundColor: Colors.white,
body: SingleChildScrollView(
child: Column(children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 60.0),
child: Center(
child: Container(
width: 300,
height: 380,
decoration:
BoxDecoration(borderRadius: BorderRadius.circular(50.0)),
child: Image.asset(
'assets/images/logo.png',
)),
),
),
const SizedBox(height: 15.0),
Form(
key: _formKey,
child: Padding(
padding: EdgeInsets.only(left: 25.0, right: 25.0, top: 0, bottom: 0),
child: TextFormField(
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter the email.';
}
return null;
},
controller: emailController,
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(60),
),
prefixIcon: const Icon(Icons.mail),
labelText: 'E-Mail',
hintText: 'admin#gmail.com'),
),
),
),
Padding(
padding: EdgeInsets.only(left: 25.0, right: 25.0, top: 15, bottom: 0),
child: TextFormField(
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter the password.';
}
return null;
},
controller: passwordController,
obscureText: true,
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(60),
),
prefixIcon: const Icon(Icons.vpn_key),
labelText: 'Password',
hintText: 'Enter your Password'),
),
),
const SizedBox(
height: 100,
),
TextButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Processing')),
);
}
authService.signInWithEmailAndPassword(context,
emailController.text.trim(), passwordController.text.trim());
},
child: const Text(
'Login',
textAlign: TextAlign.center,
)),
MaterialButton(
onPressed: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => forgotPassword()));
},
child: Text(
'Forgot Password',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 13.0, color: Colors.red.shade900),
))
])),
);
}
}
I'm a beginner in the flutter, I have a conflict, when I'm focusing on a TexFiled, the keyboard hidden over the TextField, and bottom button not showing i attached my conflict here
any solution for this
Thanks
code here
import 'dart:ui';
import 'package:crapp/pages/create_password/password_screen.dart';
import 'package:crapp/widgets/components/alert.dart';
import 'package:crapp/widgets/components/page_animation.dart';
import 'package:crapp/widgets/theme/constants.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:crapp/provider/theme_provider.dart';
class PasswordScreen extends StatefulWidget {
#override
_PasswordScreenState createState() => _PasswordScreenState();
}
class _PasswordScreenState extends State< PasswordScreen > {
final _controller = TextEditingController();
//validation controller
TextEditingController sQuastionController = new TextEditingController();
TextEditingController answerQController = new TextEditingController();
TextEditingController passController = new TextEditingController();
TextEditingController conPassController = new TextEditingController();
final TextEditingController _pass = TextEditingController();
final TextEditingController _confirmPass = TextEditingController();
bool _isButtonEnabled = false;
//final _controller = TextEditingController();
bool isConfirm=false;
check (BuildContext context){
if(sQuastionController.text.isNotEmpty &&
answerQController.text.isNotEmpty &&
conPassController.text.isNotEmpty &&
passController.text.isNotEmpty){
setState(() {
_isButtonEnabled = true;
});
} else {
setState(() {
_isButtonEnabled = false;
});
}
}
checks (BuildContext context){
if(passController.text.isEmpty){
showDialog<void>(
context: context,
builder: (BuildContext dialogContext) {
return Alert(title: "Alert !!!",subTile: "Password must be 10 characters !",);
}
);
}else if(passController.text.length > 0 && passController.text.length < 10){
isConfirm = true;
showDialog<void>(
context: context,
builder: (BuildContext dialogContext) {
return Alert(title: "Alert !!!",subTile: "Password doesn't match !",);
}
);
}
}
checkChanged(){
if( secretVal != null
)
{
setState(() {
isSave = true;
});
}else{
isSave =false;
}
} bool isSave=false;
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
/* double height = MediaQuery.of(context).size.height;
double width = MediaQuery.of(context).size.width;*/
Provider.of<ThemeProvider>(context).themeMode == ThemeMode.dark
? 'DarkTheme'
: 'LightTheme';
return Scaffold(
resizeToAvoidBottomInset: false,
body: SafeArea(
child: Column(
children: <Widget>[
Expanded(
child: _signUp(),
),
],
),
), bottomNavigationBar: BottomAppBar(
elevation: 4,
child: Container(
height: 70,
child: Container(
padding: EdgeInsets.symmetric(horizontal: 16),
child: Row(
children: [
Expanded(
child: MaterialButton(
height: 44,
onPressed: () {
FocusScope.of(context).requestFocus(FocusNode());
//check();
},
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(4)),
color: Color(0xFF2A3476),
elevation: 0,
highlightElevation: 0,
child: Container(
child: Text(
"Save",
style: TextStyle(
color: Color(0xFF2A3476),
fontSize: 15,
fontFamily: 'medium'),
),
),
),
),
],
),
),
),
),
/* bottomNavigationBar: Container(
padding: EdgeInsets.all(25.0),
decoration: BoxDecoration(color: Colors.white,
),
child: Row(
children: [
Expanded(
child: MaterialButton(
height: 44,
onPressed: () {
FocusScope.of(context).requestFocus(FocusNode());
*//* Navigator.push(context, SlidePageRoute(page:PasswordScreen()));*//*
},
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(8.0))),
color: _isButtonEnabled ? Color(0xFF2A3476) : Color(0x201E1E99),
elevation: 0,
highlightElevation: 0,
child: Container(
child: Text(
"Next",
style: TextStyle(color: m_fillColor,fontSize: 18,fontWeight: FontWeight.w600 ,
fontFamily: "regular",),
),
),
),
),
],
),
)*/
);
}
Widget _signUp() {
return Container(
constraints: BoxConstraints.expand(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
),
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Color(0xFF2A3476),
Color(0xFF2A3476),
],
begin: Alignment.topLeft,
end: Alignment.centerRight,
),
),
child: Form(
key: formKey,
child: Container(
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding:
const EdgeInsets.symmetric(vertical: 36.0, horizontal: 24.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Create Password",
style: TextStyle(
color: Colors.white,
fontSize: 30.0,fontFamily: "medium",
fontWeight: FontWeight.w800,
),
),
],
),
),
Container(
width: double.infinity,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(30),
topRight: Radius.circular(30),
),
),
child: Padding(
padding: const EdgeInsets.all(24.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Steps to set your",
style: TextStyle(
fontSize: 22,
fontFamily: "regular",
fontWeight: FontWeight.w300,
color: Colors.black,
),
),
Text(
"password",
style: TextStyle(
fontSize: 22,
fontFamily: "regular",
fontWeight: FontWeight.w300,
color: Colors.black,
),
),
SizedBox(
height: 20.0,
), Text(
'Secret Question',
style:
TextStyle( fontSize: 15,
fontFamily: "regular",),
), SizedBox(
height: 8.0,
),
Row(
children: [
Expanded(child: InkWell(
onTap: (){
FocusScope.of(context).requestFocus(FocusNode());
secretDialogue();
},
child: Stack(
children: <Widget>[
TextField(
/* textInputAction: TextInputAction.next,*/
controller: sQuastionController,
enabled: false,
onChanged: (val) {
check(context);
},
decoration: InputDecoration(
labelText: secretVal==null?"Select One":secretVal,
contentPadding: EdgeInsets.all(8),
border: OutlineInputBorder(
borderRadius:
BorderRadius.circular(8.0),
borderSide: BorderSide.none,
),
filled: true,
fillColor: Color(0xFFE1E8F7),
hintText: "",
/* prefixIcon: Icon(
Icons.people_outline_rounded,
color: Colors.grey[600],
)*/
),
),
Positioned.directional(
textDirection: Directionality.of(context),
end: 0,
top: 0,
bottom: 0,
child: Padding(
padding: const EdgeInsets.all(8.0),
child:Image.asset(
"assets/icons/ic_drop_arrow.png",
scale: 9,
)),
)
],
),
),
),
],
),
SizedBox(
height: 20.0,
),
Text(
'Answer',
style:
TextStyle( fontSize: 15,
fontFamily: "regular",),
),
SizedBox(
height: 8.0,
),
TextField(
/* keyboardType: TextInputType.emailAddress,*/
/* textInputAction: TextInputAction.next,*/
controller: answerQController,
onChanged: (val){
check(context);
},
decoration: InputDecoration(
contentPadding: EdgeInsets.all(8),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
borderSide: BorderSide.none,
),
filled: true,
fillColor: Color(0xFFE1E8F7),
hintText: "",
/*prefixIcon: Icon(
Icons.people_outline_rounded,
color: Color(0xFFE1E8F7),
)*/),
),
SizedBox(
height: 20.0,
),
Text(
'Password',
style:
TextStyle( fontSize: 15,
fontFamily: "regular",),
),
SizedBox(
height: 8.0,
),
TextFormField(
/* keyboardType: TextInputType.emailAddress,*/
/* textInputAction: TextInputAction.next,*/
controller: passController,
onChanged: (val){
check(context);
},
//password validation
/* validator: (val){
if(val!.isEmpty)
return 'Empty';
return null;
},*/
decoration: InputDecoration(
contentPadding: EdgeInsets.all(8),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
borderSide: BorderSide.none,
),
filled: true,
fillColor: Color(0xFFE1E8F7),
hintText: "************",
),
),
SizedBox(
height: 20.0,
),
Text(
'Confirm Password',
style:
TextStyle( fontSize: 15,
fontFamily: "regular",),
),
SizedBox(
height: 8.0,
),
TextFormField(
textInputAction: TextInputAction.done,
controller: conPassController,
onChanged: (val){
check(context);
},
//password validation
/* validator: (val){
if(val!.isEmpty)
return 'Empty';
if(val != _pass.text)
return 'Not Match';
return null;
},*/
decoration: InputDecoration(
contentPadding: EdgeInsets.all(8),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
borderSide: BorderSide.none,
),
filled: true,
fillColor: Color(0xFFE1E8F7),
hintText: "************",
),
),
SizedBox(
height: 20.0,
),
SizedBox(
height: 8.0,
),
SizedBox(
height:200.0,
),
],
),
),
),
],
),
),
),
),
);
}
//
//Secret Qu Alert
List secretList =[
"-What’s your favorite team?",
"-What’s your astrological sign?",
"-What’s your favorite movie?",
"-What city were you born in?",
"-What was your first car?",
];
var secretVal;
void secretDialogue(){
showDialog<void>(
context: context,
// false = user must tap button, true = tap outside dialog
builder: (BuildContext dialogContext) {
return StatefulBuilder(
builder: (context,setState){
return Dialog(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
insetPadding: EdgeInsets.all(20),
child: Container(
padding: EdgeInsets.symmetric(vertical: 10),
child: Column(
mainAxisSize: MainAxisSize.min,
children: List.generate(secretList.length, (index){
return InkWell(
onTap: (){
setState(() {
secretVal = secretList[index];
Navigator.pop(context);
});
},
child: Container(
height: 50,
padding: EdgeInsets.symmetric(horizontal: 20),
alignment: Alignment.centerLeft,
child: Text(secretList[index],
style: TextStyle(
fontSize: 18,
fontFamily: "medium",
),),
),
);
})
),
),
);
}
);
},
);
}
}
Wrap your Column by SingleChildScrollView. It will solve your problem.
like this..
body: SafeArea(
child: SingleChildScrollView(
child: Column(
Also I think after this there is no need of
resizeToAvoidBottomInset: false,
in Scaffold.
Please check out and I have found some inconsistency in code, refactored some of them
import 'dart:ui';
import 'package:crapp/pages/create_password/password_screen.dart';
import 'package:crapp/widgets/components/alert.dart';
import 'package:crapp/widgets/components/page_animation.dart';
import 'package:crapp/widgets/theme/constants.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:crapp/provider/theme_provider.dart';
class PasswordScreen extends StatefulWidget {
#override
_PasswordScreenState createState() => _PasswordScreenState();
}
class _PasswordScreenState extends State< PasswordScreen > {
final _controller = TextEditingController();
//validation controller
TextEditingController sQuastionController = new TextEditingController();
TextEditingController answerQController = new TextEditingController();
TextEditingController passController = new TextEditingController();
TextEditingController conPassController = new TextEditingController();
final TextEditingController _pass = TextEditingController();
final TextEditingController _confirmPass = TextEditingController();
bool _isButtonEnabled = false;
//final _controller = TextEditingController();
bool isConfirm = false;
check(BuildContext context) {
if (sQuastionController.text.isNotEmpty &&
answerQController.text.isNotEmpty &&
conPassController.text.isNotEmpty &&
passController.text.isNotEmpty) {
setState(() {
_isButtonEnabled = true;
});
} else {
setState(() {
_isButtonEnabled = false;
});
}
}
void initState() {
SystemChannels.textInput.invokeMethod('TextInput.hide');
super.initState();
}
checks (BuildContext context){
if(passController.text.isEmpty){
showDialog<void>(
context: context,
builder: (BuildContext dialogContext) {
return Alert(title: "Alert !!!",subTile: "Password must be 10 characters !",);
}
);
}else if(passController.text.length > 0 && passController.text.length < 10){
isConfirm = true;
showDialog<void>(
context: context,
builder: (BuildContext dialogContext) {
return Alert(title: "Alert !!!",subTile: "Password doesn't match !",);
}
);
}
}
checkChanged() {
if (secretVal != null) {
setState(() {
isSave = true;
});
} else {
isSave = false;
}
}
bool isSave = false;
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
/* double height = MediaQuery.of(context).size.height;
double width = MediaQuery.of(context).size.width;*/
Provider.of<ThemeProvider>(context).themeMode == ThemeMode.dark
? 'DarkTheme'
: 'LightTheme';
return Scaffold(
// resizeToAvoidBottomInset: false,
body: _signUp(),
bottomNavigationBar: BottomAppBar(
elevation: 4,
child: Container(
height: 70,
child: Container(
padding: EdgeInsets.symmetric(horizontal: 16),
child: Row(
children: [
Expanded(
child: MaterialButton(
height: 44,
onPressed: () {
FocusScope.of(context).requestFocus(FocusNode());
//check();
},
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(4)),
color: Color(0xFF2A3476),
elevation: 0,
highlightElevation: 0,
child: Container(
child: Text(
"Save",
style: TextStyle(
color: Color(0xFF2A3476),
fontSize: 15,
fontFamily: 'medium'),
),
),
),
),
],
),
),
),
),
/* bottomNavigationBar: Container(
padding: EdgeInsets.all(25.0),
decoration: BoxDecoration(color: Colors.white,
),
child: Row(
children: [
Expanded(
child: MaterialButton(
height: 44,
onPressed: () {
FocusScope.of(context).requestFocus(FocusNode());
*/ /* Navigator.push(context, SlidePageRoute(page:PasswordScreen()));*/ /*
},
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(8.0))),
color: _isButtonEnabled ? Color(0xFF2A3476) : Color(0x201E1E99),
elevation: 0,
highlightElevation: 0,
child: Container(
child: Text(
"Next",
style: TextStyle(color: m_fillColor,fontSize: 18,fontWeight: FontWeight.w600 ,
fontFamily: "regular",),
),
),
),
),
],
),
)*/
);
}
Widget _signUp() {
return Container(
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Color(0xFF2A3476),
Color(0xFF2A3476),
],
begin: Alignment.topLeft,
end: Alignment.centerRight,
),
),
child: SingleChildScrollView(
child: Form(
key: formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.symmetric(
vertical: 36.0, horizontal: 24.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Create Password",
style: TextStyle(
color: Colors.white,
fontSize: 30.0,
fontFamily: "medium",
fontWeight: FontWeight.w800,
),
),
],
),
),
Container(
width: double.infinity,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(30),
topRight: Radius.circular(30),
),
),
child: Padding(
padding: const EdgeInsets.all(24.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Steps to set your",
style: TextStyle(
fontSize: 22,
fontFamily: "regular",
fontWeight: FontWeight.w300,
color: Colors.black,
),
),
Text(
"password",
style: TextStyle(
fontSize: 22,
fontFamily: "regular",
fontWeight: FontWeight.w300,
color: Colors.black,
),
),
SizedBox(
height: 20.0,
),
Text(
'Secret Question',
style: TextStyle(
fontSize: 15,
fontFamily: "regular",
),
),
SizedBox(
height: 8.0,
),
Row(
children: [
Expanded(
child: InkWell(
onTap: () {
FocusScope.of(context)
.requestFocus(FocusNode());
secretDialogue();
},
child: Stack(
children: <Widget>[
TextField(
/* textInputAction: TextInputAction.next,*/
controller: sQuastionController,
enabled: false,
onChanged: (val) {
check(context);
},
decoration: InputDecoration(
labelText: secretVal == null
? "Select One"
: secretVal,
contentPadding: EdgeInsets.all(8),
border: OutlineInputBorder(
borderRadius:
BorderRadius.circular(8.0),
borderSide: BorderSide.none,
),
filled: true,
fillColor: Color(0xFFE1E8F7),
hintText: "",
/* prefixIcon: Icon(
Icons.people_outline_rounded,
color: Colors.grey[600],
)*/
),
),
Positioned.directional(
textDirection: Directionality.of(context),
end: 0,
top: 0,
bottom: 0,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Image.asset(
"assets/icons/ic_drop_arrow.png",
scale: 9,
)),
)
],
),
),
),
],
),
SizedBox(
height: 20.0,
),
Text(
'Answer',
style: TextStyle(
fontSize: 15,
fontFamily: "regular",
),
),
SizedBox(
height: 8.0,
),
GestureDetector(
onTap: () {
FocusScope.of(context).requestFocus(new FocusNode());
},
child: TextField(
/* keyboardType: TextInputType.emailAddress,*/
/* textInputAction: TextInputAction.next,*/
controller: answerQController,
onChanged: (val) {
check(context);
},
decoration: InputDecoration(
contentPadding: EdgeInsets.all(8),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
borderSide: BorderSide.none,
),
filled: true,
fillColor: Color(0xFFE1E8F7),
hintText: "",
/*prefixIcon: Icon(
Icons.people_outline_rounded,
color: Color(0xFFE1E8F7),
)*/
),
),
),
SizedBox(
height: 20.0,
),
Text(
'Password',
style: TextStyle(
fontSize: 15,
fontFamily: "regular",
),
),
SizedBox(
height: 8.0,
),
GestureDetector(
onTap: () {
FocusScope.of(context).requestFocus(new FocusNode());
},
child: TextFormField(
/* keyboardType: TextInputType.emailAddress,*/
/* textInputAction: TextInputAction.next,*/
controller: passController,
onChanged: (val) {
check(context);
},
//password validation
/* validator: (val){
if(val!.isEmpty)
return 'Empty';
return null;
},*/
decoration: InputDecoration(
contentPadding: EdgeInsets.all(8),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
borderSide: BorderSide.none,
),
filled: true,
fillColor: Color(0xFFE1E8F7),
hintText: "************",
),
),
),
SizedBox(
height: 20.0,
),
Text(
'Confirm Password',
style: TextStyle(
fontSize: 15,
fontFamily: "regular",
),
),
SizedBox(
height: 8.0,
),
GestureDetector(
onTap: () {
FocusScope.of(context).requestFocus(new FocusNode());
},
child: TextFormField(
textInputAction: TextInputAction.done,
controller: conPassController,
onChanged: (val) {
check(context);
},
//password validation
/* validator: (val){
if(val!.isEmpty)
return 'Empty';
if(val != _pass.text)
return 'Not Match';
return null;
},*/
decoration: InputDecoration(
contentPadding: EdgeInsets.all(8),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
borderSide: BorderSide.none,
),
filled: true,
fillColor: Color(0xFFE1E8F7),
hintText: "************",
),
),
),
SizedBox(
height: 20.0,
),
SizedBox(
height: 8.0,
),
SizedBox(
height: 200.0,
),
],
),
),
),
],
),
),
),
);
}
//
//Secret Qu Alert
List secretList = [
"-What’s your favorite team?",
"-What’s your astrological sign?",
"-What’s your favorite movie?",
"-What city were you born in?",
"-What was your first car?",
];
var secretVal;
void secretDialogue() {
showDialog<void>(
context: context,
// false = user must tap button, true = tap outside dialog
builder: (BuildContext dialogContext) {
return StatefulBuilder(builder: (context, setState) {
return Dialog(
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
insetPadding: EdgeInsets.all(20),
child: Container(
padding: EdgeInsets.symmetric(vertical: 10),
child: Column(
mainAxisSize: MainAxisSize.min,
children: List.generate(secretList.length, (index) {
return InkWell(
onTap: () {
setState(() {
secretVal = secretList[index];
Navigator.pop(context);
});
},
child: Container(
height: 50,
padding: EdgeInsets.symmetric(horizontal: 20),
alignment: Alignment.centerLeft,
child: Text(
secretList[index],
style: TextStyle(
fontSize: 18,
fontFamily: "medium",
),
),
),
);
})),
),
);
});
},
);
}
}
i have a button with a Text widget as child, inside a showModalBottomSheet which builds
another showModalBottomSheet holding a cupertinoPicker.
how can i return the value of cupertinopicker?
it only returns the value when i close down the first bottomsheet!! instead of doing so when the cupertinoPicker(bottomsheet) is dismissed!!
thank you all
this is my cod
FlatButton(
color: Colors.white,
onPressed: () => showModalBottomSheet<dynamic>(
isScrollControlled: true,
context: context,
builder: (BuildContext context) => Container(
child: Container(
color: Colors.black45,
child: SingleChildScrollView(
child: Column(
children: <Widget>[
Row(
children: <Widget>[
Padding(
padding:
const EdgeInsets.only(
top: 50.0,
left: 120),
child: Text(
'Gå med',
style: TextStyle(
fontSize: 34,
color:
Colors.white),
),
),
SizedBox(
width: 40,
),
FlatButton(
onPressed: () =>
Navigator.pop(
context),
child: Icon(
Icons.clear,
color: Colors.white,
),
)
],
),
Form(
key: _formKey,
child: Column(
mainAxisSize:
MainAxisSize.min,
children: <Widget>[
Padding(
padding: EdgeInsets
.symmetric(
horizontal:
30.0,
vertical: 5.0),
child: TextFormField(
decoration: InputDecoration(
labelText:
'Restaurangens namn',
labelStyle: TextStyle(
fontWeight:
FontWeight
.bold)),
validator: (input) =>
input
.trim()
.isEmpty
? 'please enter a valid name'
: null,
onSaved: (input) =>
_name = input,
),
),
Padding(
padding: EdgeInsets
.symmetric(
horizontal:
30.0,
vertical: 5.0),
child: TextFormField(
decoration: InputDecoration(
labelText:
'Email',
labelStyle: TextStyle(
fontWeight:
FontWeight
.bold)),
validator: (input) =>
!input.contains(
'#')
? 'please enter a valid email'
: null,
onSaved: (input) =>
_email = input,
),
),
Padding(
padding:
const EdgeInsets
.only(
left: 30.0,
right: 0.0),
child: Row(
children: <Widget>[
SizedBox(
width: 200,
child:
TextFormField(
decoration: InputDecoration(
labelText:
'Telefon nummer',
labelStyle: TextStyle(
fontWeight:
FontWeight.bold)),
keyboardType:
TextInputType
.phone,
validator: (input) => input
.trim()
.isEmpty
? 'please enter a valid phone Number'
: null,
onChanged:
(input) =>
tel =
input,
),
),
],
),
),
Padding(
padding:
const EdgeInsets
.only(
left: 30.0,
right: 0.0),
child: Row(
children: <Widget>[
SizedBox(
width: 200,
),
Padding(
padding:
const EdgeInsets
.only(
top: 50.0,
left: 0),
child:
CupertinoButton(
child: Text(citys[selectedcity]),
onPressed: () =>
showModalBottomSheet(
context:
context,
builder: (BuildContext
context) =>
Container(
color: Colors
.white,
height: 200,
width: MediaQuery.of(
context)
.size
.width,
child:
CupertinoPicker(
onSelectedItemChanged:
(int
index) {
setState(
() {
selectedcity = index;
print(citys[selectedcity]);
});
},
itemExtent:
30,
children: List<
Widget>.generate(
citys
.length,
(index) {
return Center(
child:
Text(citys[index]),
);
}),
),
),
)
)
)],
),
),
Padding(
padding: EdgeInsets
.symmetric(
horizontal:
30.0,
vertical: 5.0),
child: TextFormField(
controller: _pass,
decoration: InputDecoration(
labelText:
'Lösenord',
labelStyle: TextStyle(
fontWeight:
FontWeight
.bold)),
validator: (input) =>
input.length < 6
? 'must contain at least 6 characters'
: null,
onSaved: (input) =>
_password = input,
obscureText: true,
),
),
Padding(
padding: EdgeInsets
.symmetric(
horizontal:
30.0,
vertical: 0.0),
child: TextFormField(
controller:
_confirmPass,
decoration: InputDecoration(
labelText:
'Lösernord igen',
labelStyle: TextStyle(
fontWeight:
FontWeight
.bold)),
validator: (val) {
if (val !=
_pass.text) ;
return 'Not Match';
},
onSaved: (input) =>
_password = input,
obscureText: true,
),
),
SizedBox(
height: 20,
),
Container(
width: 140,
child: OutlineButton(
onPressed: _submit,
color: Colors.black,
padding:
EdgeInsets.all(
5.0),
child: Text(
'Gå med',
style: TextStyle(
color: Colors
.white,
fontSize: 18.0),
),
),
),
SizedBox(
width: 20,
),
],
),
),
],
),
),
),
),
),
child: Text(
' Registera',
style: TextStyle(
color: Colors.black, fontSize: 18.0),
))
Every showModal...
is async and has Future return type
pushes route to Navigator - so result can be poped from this route Navigator.pop(ctx, result);
Here usable example
final dateTime = await showModalBottomSheet<DateTime>(builder: widget that does Navigator.pop(context, selectedDateTime) )
if (dateTime != null) { /* do what you need */ }
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))
])),
),
))
]));
}));
}
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) {
...