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);
  }),
),