Flutter 如何使用表单和GlobalKey验证alertDialog上的文本输入?
我在Flutter 如何使用表单和GlobalKey验证alertDialog上的文本输入?,flutter,flutter-layout,Flutter,Flutter Layout,我在alertDialog上有一个textfield,它接受Email并希望验证它。点击忘记密码按钮后,alertDialog将在当前登录屏幕前打开。 我已经实现了登录验证,并尝试使用类似的逻辑来实现上述功能。对于登录验证,我使用了GlobalKey(\u formKey)和Form小部件,它们工作得非常好。我正在使用另一个名为\u resetKey的GlobalKey获取验证的currentState,然后保存其状态。尽管这种方法可行,但我看到验证消息也显示在电子邮件和密码字段中。也就是说,如
alertDialog
上有一个textfield
,它接受Email
并希望验证它。点击忘记密码
按钮后,alertDialog将在当前登录屏幕前打开。
我已经实现了登录验证,并尝试使用类似的逻辑来实现上述功能。对于登录验证,我使用了GlobalKey
(\u formKey)和Form
小部件,它们工作得非常好。我正在使用另一个名为\u resetKey
的GlobalKey
获取验证的currentState
,然后保存其状态。尽管这种方法可行,但我看到验证消息也显示在电子邮件
和密码
字段中。也就是说,如果我点击打开对话框的“忘记密码”,然后点击发送电子邮件,它会正确显示验证消息,但同时,在点击alertdialog的取消按钮后,登录屏幕的验证消息也会被触发。大概是这样的:
对于alertDialog验证,以下是我的代码:
// Creates an alertDialog for the user to enter their email
Future<String> _resetDialogBox() {
final resetEmailController = TextEditingController();
return showDialog<String>(
context: context,
barrierDismissible: false, // user must tap button!
builder: (BuildContext context) {
return AlertDialog(
title: new Text('Reset Password'),
content: new SingleChildScrollView(
child: new Form(
key: _resetKey,
autovalidate: _validate,
child: ListBody(
children: <Widget>[
new Text(
'Enter the Email Address associated with your account.',
style: TextStyle(fontSize: 14.0),),
Padding(
padding: EdgeInsets.all(10.0),
),
Row(
children: <Widget>[
new Padding(
padding: EdgeInsets.only(top: 8.0),
child: Icon(
Icons.email, size: 20.0,
),
),
new Expanded(
child: TextFormField(
validator: validateEmail,
onSaved: (String val) {
resetEmail = val;
},
new FlatButton(
child: new Text(
'SEND EMAIL', style: TextStyle(color: Colors.black),),
onPressed: () {
setState(() {
_sendResetEmail();
});
void _sendResetEmail() {
final resetEmailController = TextEditingController();
resetEmail = resetEmailController.text;
if (_resetKey.currentState.validate()) {
_resetKey.currentState.save();
try {
Fluttertoast.showToast(
msg: "Sending password-reset email to: $resetEmail",
toastLength: Toast.LENGTH_LONG,
bgcolor: "#e74c3c",
textcolor: '#ffffff',
timeInSecForIos: 4);
_auth.sendPasswordResetEmail(email: resetEmail);
} catch (exception) {
print(exception);
Fluttertoast.showToast(
msg: "${exception.toString()}",
toastLength: Toast.LENGTH_LONG,
bgcolor: "#e74c3c",
textcolor: '#ffffff',
timeInSecForIos: 4);
}
}
else {
setState(() {
_validate = true;
});
}
}
我认为这与2个键有关,因为alertDialog显示在当前活动的前面。如何使用\u formKey
实现,或者是否有其他方法
************必需的完整代码************
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: LoginScreen(),
),
);
}
}
class LoginScreen extends StatefulWidget {
@override
LoginScreenState createState() => new LoginScreenState();
}
class LoginScreenState extends State<LoginScreen> {
final FirebaseAuth _auth = FirebaseAuth.instance;
final _formKey = GlobalKey<FormState>();
final _resetKey = GlobalKey<FormState>();
bool _validate = false;
String email;
String password;
String resetEmail;
// The controller for the email field
final _emailController = TextEditingController();
// The controller for the password field
final _passwordController = TextEditingController();
// Creates the 'forgot password' and 'create account' buttons
Widget _accountButtons() {
return Container(
child: Expanded(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Container(
child: new FlatButton(
padding: const EdgeInsets.only(
top: 50.0, right: 150.0),
onPressed: () => sendPasswordResetEmail(),
child: Text("Forgot Password",
style: TextStyle(color: Colors.white)),
),
)
]),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Container(
child: new FlatButton(
padding: const EdgeInsets.only(top: 50.0),
onPressed: () =>
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => CreateAccountPage())),
child: Text(
"Register",
style: TextStyle(color: Colors.white),
),
),
)
],
)
])),
);
}
// Creates the email and password text fields
Widget _textFields() {
return Form(
key: _formKey,
autovalidate: _validate,
child: Column(
children: <Widget>[
Container(
decoration: new BoxDecoration(
border: new Border(
bottom: new BorderSide(width: 0.5, color: Colors.grey),
),
),
margin: const EdgeInsets.symmetric(
vertical: 25.0, horizontal: 65.0),
// Email text field
child: Row(
children: <Widget>[
new Padding(
padding: EdgeInsets.symmetric(
vertical: 10.0, horizontal: 15.0),
child: Icon(
Icons.email,
color: Colors.white,
),
),
new Expanded(
child: TextFormField(
validator: validateEmail,
onSaved: (String val) {
email = val;
},
keyboardType: TextInputType.emailAddress,
autofocus: true,
// cursorColor: Colors.green,
controller: _emailController,
decoration: InputDecoration(
border: InputBorder.none,
hintText: 'Email',
// contentPadding: EdgeInsets.fromLTRB(45.0, 10.0, 20.0, 1.0),
contentPadding: EdgeInsets.only(left: 55.0, top: 15.0),
hintStyle: TextStyle(color: Colors.white),
),
style: TextStyle(color: Colors.white),
),
)
],
),
),
// Password text field
Container(
decoration: new BoxDecoration(
border: new Border(
bottom: new BorderSide(
width: 0.5,
color: Colors.grey,
),
),
),
margin: const EdgeInsets.symmetric(
vertical: 10.0, horizontal: 65.0),
child: Row(
children: <Widget>[
new Padding(
padding: EdgeInsets.symmetric(
vertical: 10.0, horizontal: 15.0),
child: Icon(
Icons.lock,
color: Colors.white,
),
),
new Expanded(
child: TextFormField(
validator: _validatePassword,
onSaved: (String val) {
password = val;
},
// cursorColor: Colors.green,
controller: _passwordController,
decoration: InputDecoration(
border: InputBorder.none,
hintText: 'Password',
contentPadding: EdgeInsets.only(
left: 50.0, top: 15.0),
hintStyle: TextStyle(color: Colors.white),
),
style: TextStyle(color: Colors.white),
// Make the characters in this field hidden
obscureText: true),
)
],
),
)
],
)
);
}
// Creates the button to sign in
Widget _signInButton() {
return new Container(
width: 200.0,
margin: const EdgeInsets.only(top: 20.0),
padding: const EdgeInsets.only(left: 20.0, right: 20.0),
child: new Row(
children: <Widget>[
new Expanded(
child: RaisedButton(
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(30.0)),
splashColor: Colors.white,
color: Colors.green,
child: new Row(
children: <Widget>[
new Padding(
padding: const EdgeInsets.only(left: 35.0),
child: Text(
"Sign in",
style: TextStyle(color: Colors.white, fontSize: 18.0),
textAlign: TextAlign.center,
),
),
],
),
onPressed: () {
setState(() {
_signIn();
});
}),
),
],
));
}
// Signs in the user
void _signIn() async {
// Grab the text from the text fields
final email = _emailController.text;
final password = _passwordController.text;
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
try {
Fluttertoast.showToast(
msg: "Signing in...",
toastLength: Toast.LENGTH_LONG,
bgcolor: "#e74c3c",
textcolor: '#ffffff',
timeInSecForIos: 2);
firebaseUser = await _auth.signInWithEmailAndPassword(
email: email, password: password);
// If user successfully signs in, go to the pro categories page
Navigator.pushReplacement(context,
MaterialPageRoute(
builder: (context) => ProCategories(firebaseUser)));
} catch (exception) {
print(exception.toString());
Fluttertoast.showToast(
msg: "${exception.toString()}",
toastLength: Toast.LENGTH_LONG,
bgcolor: "#e74c3c",
textcolor: '#ffffff',
timeInSecForIos: 3);
}
}
else {
setState(() {
_validate = true;
});
}
}
// Creates an alertDialog for the user to enter their email
Future<String> _resetDialogBox() {
final resetEmailController = TextEditingController();
return showDialog<String>(
context: context,
barrierDismissible: false, // user must tap button!
builder: (BuildContext context) {
return AlertDialog(
title: new Text('Reset Password'),
content: new SingleChildScrollView(
child: new Form(
key: _resetKey,
autovalidate: _validate,
child: ListBody(
children: <Widget>[
new Text(
'Enter the Email Address associated with your account.',
style: TextStyle(fontSize: 14.0),),
Padding(
padding: EdgeInsets.all(10.0),
),
Row(
children: <Widget>[
new Padding(
padding: EdgeInsets.only(top: 8.0),
child: Icon(
Icons.email, size: 20.0,
),
),
new Expanded(
child: TextFormField(
validator: validateEmail,
onSaved: (String val) {
resetEmail = val;
},
keyboardType: TextInputType.emailAddress,
autofocus: true,
decoration: new InputDecoration(
border: InputBorder.none,
hintText: 'Email',
contentPadding: EdgeInsets.only(
left: 70.0, top: 15.0),
hintStyle: TextStyle(
color: Colors.black, fontSize: 14.0)
),
style: TextStyle(color: Colors.black),
),
)
],
),
new Column(
children: <Widget>[
Container(
decoration: new BoxDecoration(
border: new Border(
bottom: new BorderSide(
width: 0.5, color: Colors.black)
)
),
)
]
),
],
),
)
),
actions: <Widget>[
new FlatButton(
child: new Text('CANCEL', style: TextStyle(color: Colors.black),),
onPressed: () {
Navigator.of(context).pop("");
},
),
new FlatButton(
child: new Text(
'SEND EMAIL', style: TextStyle(color: Colors.black),),
onPressed: () {
setState(() {
_sendResetEmail();
});
Navigator.of(context).pop(resetEmail);
},
),
],
);
},
);
}
// Sends a password-reset link to the given email address
void sendPasswordResetEmail() async {
String resetEmail = await _resetDialogBox();
// When this is true, the user pressed 'cancel', so do nothing
if (resetEmail == "") {
return;
}
try {
Fluttertoast.showToast(
msg: "Sending password-reset email to: $resetEmail",
toastLength: Toast.LENGTH_LONG,
bgcolor: "#e74c3c",
textcolor: '#ffffff',
timeInSecForIos: 4);
_auth.sendPasswordResetEmail(email: resetEmail);
} catch (exception) {
print(exception);
Fluttertoast.showToast(
msg: "${exception.toString()}",
toastLength: Toast.LENGTH_LONG,
bgcolor: "#e74c3c",
textcolor: '#ffffff',
timeInSecForIos: 4);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
// prevent pixel overflow when typing
resizeToAvoidBottomPadding: false,
body: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(
"",
),
fit: BoxFit.cover)),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
// QuickCarl logo at the top
Image(
alignment: Alignment.bottomCenter,
image: AssetImage(""),
width: 180.0,
height: 250.0,
),
new Text('',
style: TextStyle(
fontStyle: FontStyle.italic,
fontSize: 12.0,
color: Colors.white)
),
_textFields(),
_signInButton(),
_accountButtons()
],
),
),
);
}
String validateEmail(String value) {
String pattern = r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$';
RegExp regExp = new RegExp(pattern);
if (value.length == 0) {
return "Email is required";
} else if (!regExp.hasMatch(value)) {
return "Invalid Email";
} else {
return null;
}
}
String _validatePassword(String value) {
if (value.length == 0) {
return 'Password is required';
}
if (value.length < 4) {
return 'Incorrect password';
}
}
void _sendResetEmail() {
final resetEmailController = TextEditingController();
resetEmail = resetEmailController.text;
if (_resetKey.currentState.validate()) {
_resetKey.currentState.save();
try {
Fluttertoast.showToast(
msg: "Sending password-reset email to: $resetEmail",
toastLength: Toast.LENGTH_LONG,
bgcolor: "#e74c3c",
textcolor: '#ffffff',
timeInSecForIos: 4);
_auth.sendPasswordResetEmail(email: resetEmail);
} catch (exception) {
print(exception);
Fluttertoast.showToast(
msg: "${exception.toString()}",
toastLength: Toast.LENGTH_LONG,
bgcolor: "#e74c3c",
textcolor: '#ffffff',
timeInSecForIos: 4);
}
}
else {
setState(() {
_validate = true;
});
}
}
}
void main()=>runApp(MyApp());
类MyApp扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回材料PP(
家:脚手架(
正文:LoginScreen(),
),
);
}
}
类LoginScreen扩展StatefulWidget{
@凌驾
LoginScreenState createState()=>新LoginScreenState();
}
类LoginScreenState扩展了状态{
final FirebaseAuth _auth=FirebaseAuth.instance;
final _formKey=GlobalKey();
最终_resetKey=GlobalKey();
bool _validate=false;
字符串电子邮件;
字符串密码;
字符串重置电子邮件;
//电子邮件字段的控制器
final _emailController=TextEditingController();
//密码字段的控制器
final _passwordController=TextEditingController();
//创建“忘记密码”和“创建帐户”按钮
小部件_accountButtons(){
返回容器(
儿童:扩大(
孩子:排(
mainAxisAlignment:mainAxisAlignment.spaceAround,
儿童:[
划船(
mainAxisAlignment:mainAxisAlignment.space,
儿童:[
容器(
孩子:新的扁平按钮(
填充:仅限常量边设置(
顶部:50.0,右侧:150.0),
onPressed:()=>sendPasswordResetEmail(),
子项:文本(“忘记密码”,
样式:TextStyle(颜色:Colors.white)),
),
)
]),
划船(
mainAxisAlignment:mainAxisAlignment.spaceAround,
儿童:[
容器(
孩子:新的扁平按钮(
填充:仅限常量边集(顶部:50.0),
按下:()=>
导航器。推(
上下文
材料路线(
生成器:(上下文)=>CreateAccountPage()),
子:文本(
“注册”,
样式:TextStyle(颜色:Colors.white),
),
),
)
],
)
])),
);
}
//创建电子邮件和密码文本字段
小部件_textFields(){
报税表(
键:_formKey,
自动验证:_验证,
子:列(
儿童:[
容器(
装饰:新盒子装饰(
边界:新边界(
底部:新边框(宽度:0.5,颜色:颜色。灰色),
),
),
边距:常量边集。对称(
垂直:25.0,水平:65.0),
//电子邮件文本字段
孩子:排(
儿童:[
新填料(
填充:EdgeInsets.symmetric(
垂直:10.0,水平:15.0),
子:图标(
Icons.email,
颜色:颜色,白色,
),
),
新扩展(
子项:TextFormField(
验证器:validateEmail,
onSaved:(字符串val){
email=val;
},
键盘类型:TextInputType.emailAddress,
自动对焦:对,
//光标颜色:Colors.green,
控制器:\u电子邮件控制器,
装饰:输入装饰(
边框:InputBorder.none,
hintText:“电子邮件”,
//内容填充:来自LTRB(45.0,10.0,20.0,1.0)的EdgeInsets,
contentPadding:仅限边集(左:55.0,顶:15.0),
hintStyle:TextStyle(颜色:Colors.white),
),
样式:TextStyle(颜色:Colors.white),
),
)
],
),
),
//密码文本字段
容器(
装饰:新盒子装饰(
边界:新边界(
底部:新边线(
宽度:0.5,
颜色:颜色。灰色,
),
),
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: LoginScreen(),
),
);
}
}
class LoginScreen extends StatefulWidget {
@override
LoginScreenState createState() => new LoginScreenState();
}
class LoginScreenState extends State<LoginScreen> {
final FirebaseAuth _auth = FirebaseAuth.instance;
final _formKey = GlobalKey<FormState>();
final _resetKey = GlobalKey<FormState>();
bool _validate = false;
String email;
String password;
String resetEmail;
// The controller for the email field
final _emailController = TextEditingController();
// The controller for the password field
final _passwordController = TextEditingController();
// Creates the 'forgot password' and 'create account' buttons
Widget _accountButtons() {
return Container(
child: Expanded(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Container(
child: new FlatButton(
padding: const EdgeInsets.only(
top: 50.0, right: 150.0),
onPressed: () => sendPasswordResetEmail(),
child: Text("Forgot Password",
style: TextStyle(color: Colors.white)),
),
)
]),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Container(
child: new FlatButton(
padding: const EdgeInsets.only(top: 50.0),
onPressed: () =>
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => CreateAccountPage())),
child: Text(
"Register",
style: TextStyle(color: Colors.white),
),
),
)
],
)
])),
);
}
// Creates the email and password text fields
Widget _textFields() {
return Form(
key: _formKey,
autovalidate: _validate,
child: Column(
children: <Widget>[
Container(
decoration: new BoxDecoration(
border: new Border(
bottom: new BorderSide(width: 0.5, color: Colors.grey),
),
),
margin: const EdgeInsets.symmetric(
vertical: 25.0, horizontal: 65.0),
// Email text field
child: Row(
children: <Widget>[
new Padding(
padding: EdgeInsets.symmetric(
vertical: 10.0, horizontal: 15.0),
child: Icon(
Icons.email,
color: Colors.white,
),
),
new Expanded(
child: TextFormField(
validator: validateEmail,
onSaved: (String val) {
email = val;
},
keyboardType: TextInputType.emailAddress,
autofocus: true,
// cursorColor: Colors.green,
controller: _emailController,
decoration: InputDecoration(
border: InputBorder.none,
hintText: 'Email',
// contentPadding: EdgeInsets.fromLTRB(45.0, 10.0, 20.0, 1.0),
contentPadding: EdgeInsets.only(left: 55.0, top: 15.0),
hintStyle: TextStyle(color: Colors.white),
),
style: TextStyle(color: Colors.white),
),
)
],
),
),
// Password text field
Container(
decoration: new BoxDecoration(
border: new Border(
bottom: new BorderSide(
width: 0.5,
color: Colors.grey,
),
),
),
margin: const EdgeInsets.symmetric(
vertical: 10.0, horizontal: 65.0),
child: Row(
children: <Widget>[
new Padding(
padding: EdgeInsets.symmetric(
vertical: 10.0, horizontal: 15.0),
child: Icon(
Icons.lock,
color: Colors.white,
),
),
new Expanded(
child: TextFormField(
validator: _validatePassword,
onSaved: (String val) {
password = val;
},
// cursorColor: Colors.green,
controller: _passwordController,
decoration: InputDecoration(
border: InputBorder.none,
hintText: 'Password',
contentPadding: EdgeInsets.only(
left: 50.0, top: 15.0),
hintStyle: TextStyle(color: Colors.white),
),
style: TextStyle(color: Colors.white),
// Make the characters in this field hidden
obscureText: true),
)
],
),
)
],
)
);
}
// Creates the button to sign in
Widget _signInButton() {
return new Container(
width: 200.0,
margin: const EdgeInsets.only(top: 20.0),
padding: const EdgeInsets.only(left: 20.0, right: 20.0),
child: new Row(
children: <Widget>[
new Expanded(
child: RaisedButton(
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(30.0)),
splashColor: Colors.white,
color: Colors.green,
child: new Row(
children: <Widget>[
new Padding(
padding: const EdgeInsets.only(left: 35.0),
child: Text(
"Sign in",
style: TextStyle(color: Colors.white, fontSize: 18.0),
textAlign: TextAlign.center,
),
),
],
),
onPressed: () {
setState(() {
_signIn();
});
}),
),
],
));
}
// Signs in the user
void _signIn() async {
// Grab the text from the text fields
final email = _emailController.text;
final password = _passwordController.text;
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
try {
Fluttertoast.showToast(
msg: "Signing in...",
toastLength: Toast.LENGTH_LONG,
bgcolor: "#e74c3c",
textcolor: '#ffffff',
timeInSecForIos: 2);
firebaseUser = await _auth.signInWithEmailAndPassword(
email: email, password: password);
// If user successfully signs in, go to the pro categories page
Navigator.pushReplacement(context,
MaterialPageRoute(
builder: (context) => ProCategories(firebaseUser)));
} catch (exception) {
print(exception.toString());
Fluttertoast.showToast(
msg: "${exception.toString()}",
toastLength: Toast.LENGTH_LONG,
bgcolor: "#e74c3c",
textcolor: '#ffffff',
timeInSecForIos: 3);
}
}
else {
setState(() {
_validate = true;
});
}
}
// Creates an alertDialog for the user to enter their email
Future<String> _resetDialogBox() {
final resetEmailController = TextEditingController();
return showDialog<String>(
context: context,
barrierDismissible: false, // user must tap button!
builder: (BuildContext context) {
return AlertDialog(
title: new Text('Reset Password'),
content: new SingleChildScrollView(
child: new Form(
key: _resetKey,
autovalidate: _validate,
child: ListBody(
children: <Widget>[
new Text(
'Enter the Email Address associated with your account.',
style: TextStyle(fontSize: 14.0),),
Padding(
padding: EdgeInsets.all(10.0),
),
Row(
children: <Widget>[
new Padding(
padding: EdgeInsets.only(top: 8.0),
child: Icon(
Icons.email, size: 20.0,
),
),
new Expanded(
child: TextFormField(
validator: validateEmail,
onSaved: (String val) {
resetEmail = val;
},
keyboardType: TextInputType.emailAddress,
autofocus: true,
decoration: new InputDecoration(
border: InputBorder.none,
hintText: 'Email',
contentPadding: EdgeInsets.only(
left: 70.0, top: 15.0),
hintStyle: TextStyle(
color: Colors.black, fontSize: 14.0)
),
style: TextStyle(color: Colors.black),
),
)
],
),
new Column(
children: <Widget>[
Container(
decoration: new BoxDecoration(
border: new Border(
bottom: new BorderSide(
width: 0.5, color: Colors.black)
)
),
)
]
),
],
),
)
),
actions: <Widget>[
new FlatButton(
child: new Text('CANCEL', style: TextStyle(color: Colors.black),),
onPressed: () {
Navigator.of(context).pop("");
},
),
new FlatButton(
child: new Text(
'SEND EMAIL', style: TextStyle(color: Colors.black),),
onPressed: () {
setState(() {
_sendResetEmail();
});
Navigator.of(context).pop(resetEmail);
},
),
],
);
},
);
}
// Sends a password-reset link to the given email address
void sendPasswordResetEmail() async {
String resetEmail = await _resetDialogBox();
// When this is true, the user pressed 'cancel', so do nothing
if (resetEmail == "") {
return;
}
try {
Fluttertoast.showToast(
msg: "Sending password-reset email to: $resetEmail",
toastLength: Toast.LENGTH_LONG,
bgcolor: "#e74c3c",
textcolor: '#ffffff',
timeInSecForIos: 4);
_auth.sendPasswordResetEmail(email: resetEmail);
} catch (exception) {
print(exception);
Fluttertoast.showToast(
msg: "${exception.toString()}",
toastLength: Toast.LENGTH_LONG,
bgcolor: "#e74c3c",
textcolor: '#ffffff',
timeInSecForIos: 4);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
// prevent pixel overflow when typing
resizeToAvoidBottomPadding: false,
body: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(
"",
),
fit: BoxFit.cover)),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
// QuickCarl logo at the top
Image(
alignment: Alignment.bottomCenter,
image: AssetImage(""),
width: 180.0,
height: 250.0,
),
new Text('',
style: TextStyle(
fontStyle: FontStyle.italic,
fontSize: 12.0,
color: Colors.white)
),
_textFields(),
_signInButton(),
_accountButtons()
],
),
),
);
}
String validateEmail(String value) {
String pattern = r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$';
RegExp regExp = new RegExp(pattern);
if (value.length == 0) {
return "Email is required";
} else if (!regExp.hasMatch(value)) {
return "Invalid Email";
} else {
return null;
}
}
String _validatePassword(String value) {
if (value.length == 0) {
return 'Password is required';
}
if (value.length < 4) {
return 'Incorrect password';
}
}
void _sendResetEmail() {
final resetEmailController = TextEditingController();
resetEmail = resetEmailController.text;
if (_resetKey.currentState.validate()) {
_resetKey.currentState.save();
try {
Fluttertoast.showToast(
msg: "Sending password-reset email to: $resetEmail",
toastLength: Toast.LENGTH_LONG,
bgcolor: "#e74c3c",
textcolor: '#ffffff',
timeInSecForIos: 4);
_auth.sendPasswordResetEmail(email: resetEmail);
} catch (exception) {
print(exception);
Fluttertoast.showToast(
msg: "${exception.toString()}",
toastLength: Toast.LENGTH_LONG,
bgcolor: "#e74c3c",
textcolor: '#ffffff',
timeInSecForIos: 4);
}
}
else {
setState(() {
_validate = true;
});
}
}
}
// Creates an alertDialog for the user to enter their email
Future<String> _resetDialogBox() {
return showDialog<String>(
context: context,
barrierDismissible: false, // user must tap button!
builder: (BuildContext context) {
return CustomAlertDialog(
title: "Reset email",
auth: _auth,
);
},
);
}
class CustomAlertDialog extends StatefulWidget {
final String title;
final FirebaseAuth auth;
const CustomAlertDialog({Key key, this.title, this.auth})
: super(key: key);
@override
CustomAlertDialogState createState() {
return new CustomAlertDialogState();
}
}
class CustomAlertDialogState extends State<CustomAlertDialog> {
final _resetKey = GlobalKey<FormState>();
final _resetEmailController = TextEditingController();
String _resetEmail;
bool _resetValidate = false;
StreamController<bool> rebuild = StreamController<bool>();
bool _sendResetEmail() {
_resetEmail = _resetEmailController.text;
if (_resetKey.currentState.validate()) {
_resetKey.currentState.save();
try {
// You could consider using async/await here
widget.auth.sendPasswordResetEmail(email: _resetEmail);
return true;
} catch (exception) {
print(exception);
}
} else {
setState(() {
_resetValidate = true;
});
return false;
}
}
@override
Widget build(BuildContext context) {
return Container(
child: AlertDialog(
title: new Text(widget.title),
content: new SingleChildScrollView(
child: Form(
key: _resetKey,
autovalidate: _resetValidate,
child: ListBody(
children: <Widget>[
new Text(
'Enter the Email Address associated with your account.',
style: TextStyle(fontSize: 14.0),
),
Padding(
padding: EdgeInsets.all(10.0),
),
Row(
children: <Widget>[
new Padding(
padding: EdgeInsets.only(top: 8.0),
child: Icon(
Icons.email,
size: 20.0,
),
),
new Expanded(
child: TextFormField(
validator: validateEmail,
onSaved: (String val) {
_resetEmail = val;
},
controller: _resetEmailController,
keyboardType: TextInputType.emailAddress,
autofocus: true,
decoration: new InputDecoration(
border: InputBorder.none,
hintText: 'Email',
contentPadding:
EdgeInsets.only(left: 70.0, top: 15.0),
hintStyle:
TextStyle(color: Colors.black, fontSize: 14.0)),
style: TextStyle(color: Colors.black),
),
)
],
),
new Column(children: <Widget>[
Container(
decoration: new BoxDecoration(
border: new Border(
bottom: new BorderSide(
width: 0.5, color: Colors.black))),
)
]),
],
),
),
),
actions: <Widget>[
new FlatButton(
child: new Text(
'CANCEL',
style: TextStyle(color: Colors.black),
),
onPressed: () {
Navigator.of(context).pop("");
},
),
new FlatButton(
child: new Text(
'SEND EMAIL',
style: TextStyle(color: Colors.black),
),
onPressed: () {
if (_sendResetEmail()) {
Navigator.of(context).pop(_resetEmail);
}
},
),
],
),
);
}
}
String validateEmail(String value) {
String pattern =
r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$';
RegExp regExp = new RegExp(pattern);
if (value.length == 0) {
return "Email is required";
} else if (!regExp.hasMatch(value)) {
return "Invalid Email";
} else {
return null;
}
}
final TextEditingController _nameController = TextEditingController();
final TextEditingController _phoneController = TextEditingController();
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final GlobalKey<FormFieldState> _nameFormKey = GlobalKey<FormFieldState>();
final GlobalKey<FormFieldState> _phoneFormKey = GlobalKey<FormFieldState>();
bool _isFormValid() {
return ((_nameFormKey.currentState.isValid &&
_phoneFormKey.currentState.isValid));
}
void _submit() {
print('Name: ' +
_nameController.text +
', problem: ' +
_phoneController.text);
}
Future<void> _registerDialogBox(BuildContext context) async {
return await showDialog<String>(
context: context,
barrierDismissible: false,
builder: (context) {
bool _isSubmitButtonEnabled = false;
return StatefulBuilder(builder: (context, setState) {
return AlertDialog(
scrollable: true,
title: Text('Register'),
content: Padding(
padding: const EdgeInsets.all(8.0),
child: Form(
key: _formKey,
child: Column(
children: <Widget>[
new TextFormField(
key: _nameFormKey,
controller: _nameController,
maxLength: 30,
maxLengthEnforced: true,
keyboardType: TextInputType.name,
inputFormatters: [new FilteringTextInputFormatter.allow(RegExp("[a-zA-Z]")), ],
decoration: InputDecoration(
labelText: 'Name',
icon: Icon(Icons.account_box),
),
onChanged: (value) {
setState(() {
_isSubmitButtonEnabled = _isFormValid();
_nameFormKey.currentState.validate();
});
},
validator: (value) {
if (value.length < 3 )
return 'Min 3 and Max 30 characters';
else
return null;
}),
new TextFormField(
key: _phoneFormKey,
maxLength: 13,
maxLengthEnforced: true,
controller: _phoneController,
keyboardType: TextInputType.phone,
inputFormatters: [new FilteringTextInputFormatter.allow(RegExp("[0-9+]"))],
decoration: InputDecoration(
labelText: 'Phone',
icon: Icon(Icons.phone),
),
onChanged: (value) {
setState(() {
_isSubmitButtonEnabled = _isFormValid();
_phoneFormKey.currentState.validate();
});
},
validator: (value) {
if (value.length > 1 && value.length < 10 )
return 'Minimum 10 digits';
else
return null;
}),
],
),
),
),
actions: [
RaisedButton(
child: Text("Submit"),
onPressed: _isSubmitButtonEnabled ? () => _submit() : null)
],
);
});
});
}
Padding(
padding: EdgeInsets.only(top: 5.0, bottom: 20.0),
child: RaisedButton(onPressed: ()async {
await _registerDialogBox(context);
}),
),