Login and Signup form not validating

Viewed 37

Login/Signup form is supposed to move to homepage on validation of the submit button (an arrow forward button icon) and if not validated, it ought to show a snackbar saying 'Error', but nothing works. It keeps on giving this error message on button click "Another exception was thrown: NoSuchMethodError: The method 'validate' was called on null."

Here is my code:

import 'package:flutter/cupertino.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:community_material_icon/community_material_icon.dart';
import 'package:time_to_eat_devotionals/screens/home.dart';
import 'package:time_to_eat_devotionals/theme/palette.dart';

class LoginSignupScreen extends StatefulWidget {
  @override
  _LoginSignupScreenState createState() => _LoginSignupScreenState();
}

class _LoginSignupScreenState extends State<LoginSignupScreen> {
  bool isSignUpScreen = true;
  bool isRememberMe = false;

  final _formkey = GlobalKey<FormState>();
  TextEditingController usernameController = TextEditingController();
  TextEditingController emailController = TextEditingController();
  TextEditingController passwordController = TextEditingController();
  TextEditingController nationalityController = TextEditingController();

  var countryName = ['Nigeria', 'Ghana'];

  @override
  Widget build(BuildContext context) {
    return Container(

      decoration: BoxDecoration(
        gradient: LinearGradient(
          begin: Alignment.topLeft,
          end: Alignment.bottomRight,
          colors: [Colors.yellow, Palette.backgroundColor]
        ),
      ),

      child: Scaffold(
        backgroundColor: Colors.transparent,
        body: Stack(
          children: [

            Positioned(
              top: 0,
              right: 0,
              left: 0,
              child: Container(
                height: 300,
                decoration: BoxDecoration(
                    image: DecorationImage(
                        image: AssetImage(isSignUpScreen? 'assets/images/signupbg.jpg' : 'assets/images/loginbg.jpg'),
                        fit: BoxFit.fill)),
                child: Container(
                  padding: EdgeInsets.only(top: 90, left: 20),
                  color: Colors.black.withOpacity(.65),
                  child: Column(
                    children: [
                      RichText(
                          text: TextSpan(
                              text: isSignUpScreen? 'Welcome To' : 'Welcome Back',
                              style: TextStyle(
                                  fontFamily: 'Raleway',
                                  fontSize: 18,
                                  color: Colors.white))),
                      Container(
                        height: 8.0,
                      ),
                      
                      Text(
                        'Time To Eat Devotionals',
                        style: TextStyle(
                            fontFamily: 'Kurale',
                            fontWeight: FontWeight.w600,
                            fontSize: 30.0,
                            color: Colors.white),
                      ),
                      
                      Container(
                        height: 8.0,
                      ),
                      
                      Text(
                        isSignUpScreen? 'Signup to continue': 'Login to continue',
                        style: TextStyle(
                            fontFamily: 'Raleway',
                            fontSize: 14.0,
                            color: Colors.white),
                      )
                    ],
                  ),
                ),
              ),
            ),
            
            AnimatedPositioned(
                duration: Duration(milliseconds: 700),
                curve: Curves.bounceOut,
                top: isSignUpScreen? 200 : 250,

                child: AnimatedContainer(
                  duration: Duration(milliseconds: 700),
                  curve: Curves.bounceOut,
                  padding: EdgeInsets.only(top: 5, bottom: 20, right: 20, left: 20),
                  height: isSignUpScreen? 350 : 280,
                  width: MediaQuery.of(context).size.width - 40,
                  margin: EdgeInsets.symmetric(horizontal: 20),
                  decoration: BoxDecoration(
                      color: Colors.white,
                      borderRadius: BorderRadius.circular(15),
                      boxShadow: [
                        BoxShadow(
                            color: Colors.black.withOpacity(0.3),
                            blurRadius: 15,
                            spreadRadius: 5)
                      ]),

                  child: SingleChildScrollView(
                    child: Column(
                      children: [
                  
                        Row(
                          mainAxisAlignment: MainAxisAlignment.spaceAround,
                          children: [
                  
                            GestureDetector(
                              onTap: () {
                                setState(() {
                                  isSignUpScreen = true;
                                });
                              },
                              child: Column(
                                children: [
                                  Text(
                                    "SIGNUP",
                                    style: TextStyle(
                                        fontFamily: 'baloo da 2',
                                        fontSize: 21,
                                        fontWeight: FontWeight.w500,
                                        color: isSignUpScreen
                                            ? Palette.activeColor
                                            : Colors.black),
                                  ),
                                  if (isSignUpScreen)
                                    Container(
                                      margin: EdgeInsets.only(top: 1.0),
                                      height: 2,
                                      width: 55,
                                      color: Colors.black,
                                    )
                                ],
                              ),
                            ),
                            
                            GestureDetector(
                                onTap: () {
                                  setState(() {
                                    isSignUpScreen = false;
                                  });
                                },
                                child: Column(
                                  children: [
                                    Text(
                                      "LOGIN",
                                      style: TextStyle(
                                          fontFamily: 'baloo da 2',
                                          fontSize: 21,
                                          fontWeight: FontWeight.w500,
                                          color: isSignUpScreen
                                              ? Colors.black
                                              : Palette.activeColor),
                                    ),
                                    if (!isSignUpScreen)
                                      Container(
                                        margin: EdgeInsets.only(top: 1.0),
                                        height: 2,
                                        width: 55,
                                        color: Colors.black,
                                      )
                                  ],
                                )),
                          ],
                        ),

                        isSignUpScreen?
                  
                      Container(
                        key: _formkey,
                        margin: EdgeInsets.only(top: 10),
                        child: Column(
                        children: [
                          buidTextField(Icons.person, 'User Name', 'Enter your user name', false, false, usernameController, (username){
                            if (username.isEmpty) {
                              return 'Username is required';
                            } else if (username.length <6) {
                              return 'Username is short';
                            }
                            return null;
                          }),
                          buidTextField(Icons.email, 'Email', 'Enter your valid email address', false, true, emailController, (signupEmail){
                            if (signupEmail.isEmpty) {
                              return 'Email is required';
                            } else if (!signupEmail.contains('@')) {
                              return 'Please enter a valid email address';
                            }
                            return null;
                          }),
                          buidTextField(Icons.lock, 'Password', 'Enter your password', true, false, passwordController, (signupPword){
                            if (signupPword.isEmpty) {
                              return 'Password is required';
                            } else if (signupPword.length <8) {
                              return 'Password must be at least 8 characters';
                            }
                            return null;
                          }),
                          buidTextField(Icons.flag, 'Nationality', 'What country are you from', false, false, nationalityController, (nationality){
                            if (nationality.isEmpty) {
                              return 'Enter Your Nationality';
                            } else if (!nationality.contain(countryName)) {
                              return 'Please enter a valid Country name';
                            }
                            return null;
                          }),

                          RichText(
                            textAlign: TextAlign.center,
                            text: TextSpan(
                              text: "By pressing 'Submit', you agree to our \n",
                              style: TextStyle(
                                color: Colors.black,
                                fontFamily: 'raleway',
                                fontSize: 13.0, letterSpacing: 0.1
                              ),
                              children: [
                                TextSpan(
                                  recognizer: TapGestureRecognizer()
                                  ..onTap = () {
                                    print('T&C is clicked');
                                  },
                                  text: 'Terms and Conditions',
                                  style: TextStyle(
                                    color: Palette.backgroundColor,
                                    fontFamily: 'raleway',
                                    fontSize: 13.0, letterSpacing: 0.1,
                                    fontWeight: FontWeight.w500
                                  )
                                )
                              ]
                            ),
                          ),

                        ],
                      ),) 
                      
                      : 

                      Container(
                        key: _formkey,
                        margin: EdgeInsets.only(top: 20),
                        child: Column(
                          children: [
                              buidTextField(Icons.email, 'Email', 'info@example.com', false, true, emailController, (signinEmail){
                                if (signinEmail.isEmpty) {
                              return 'Username is required';
                            } else if (signinEmail.length <6) {
                              return 'Username is short';
                            }
                            return null;
                              }),
                              buidTextField(Icons.lock, 'Password', '********', true, false, passwordController, (signinPword){
                                if (signinPword.isEmpty) {
                              return 'Password is required';
                            } else if (signinPword.length <8) {
                              return 'Password should be at least 8 characters';
                            }
                            return null;
                              }),
                  
                              Row(
                                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                                children: [
                                  Row(children: [
                                    Checkbox(
                                      value: isRememberMe, 
                                      activeColor: Colors.black,
                                      onChanged: (value) {
                                        setState(() {
                                          isRememberMe = !isRememberMe;
                                        });
                                      }
                                    ),
                                    Text(
                                      "Remember Me",
                                      style: TextStyle(
                                        fontFamily: 'raleway',
                                        fontSize: 15.0,
                                      ),
                                    )
                                  ],),
                  
                                  TextButton(
                                    onPressed: () {
                                      print('Forgot Password clicked');
                                    }, 
                                    child: Text(
                                      'Forgot Password?',
                                      style: TextStyle(
                                        fontFamily: 'raleway',
                                        fontSize: 15.0,
                                        color: Palette.backgroundColor
                                      )
                                    )
                                  )
                                ],
                              )
                          ],
                        )
                      )

                      ],
                    ),
                  ),
                )),

            AnimatedPositioned(
              duration: Duration(milliseconds: 700),
              curve: Curves.easeIn,
              top: isSignUpScreen? 500 : 480,
              right: 0,
              left:0,
              child: Center(
                child: Container(
                  padding: EdgeInsets.all(15),
                  height: 90,
                  width: 90,
                  decoration: BoxDecoration(
                    color: Colors.white,
                    borderRadius: BorderRadius.circular(50),
                  ),
                  child: Container(
                    decoration: BoxDecoration(
                      gradient: LinearGradient(
                        colors: [Colors.yellow, Palette.backgroundColor]),
                        borderRadius: BorderRadius.circular(30),
                        boxShadow: [
                          BoxShadow(
                            color: Colors.black.withOpacity(.3),
                            spreadRadius: 1,
                            blurRadius: 2,
                            offset: Offset(0, 1)
                          ),
                        ]
                    ),

                    child: IconButton(
                      onPressed: () {
                        setState(() {
                          if (_formkey.currentState.validate()) {
                          Navigator.push(context, MaterialPageRoute(builder: (context) => Home()));
                        } else {
                          ScaffoldMessenger.of(context).showSnackBar(
                            SnackBar(content: Text('Error'))
                          );
                        }
                        });
                      }, 
                      icon: Icon(Icons.arrow_forward, color: Colors.white,)
                    ),

                  ),
                ),
              )
            ),

            Positioned(
              top: MediaQuery.of(context).size.height-100,
              right: 0,
              left: 0,
              child: Column(
                children: [

                  Text(
                    "Or Signup with",
                    style: TextStyle(
                      fontFamily: 'raleway',
                      fontSize:15.0,
                      color: Colors.white,
                      fontWeight: FontWeight.w600
                    ),
                  ),

                  SizedBox(height: 10,),

                  Row(
                    mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                    children: [
                      buildTextButton(CommunityMaterialIcons.facebook, 'Facebook', Palette.fbColor),
                      buildTextButton(CommunityMaterialIcons.google, 'Google', Palette.googleColor),
                    ],
                  )

                ],
              )
            )

          ],
        ),
      ),
    );
  }

  TextButton buildTextButton(IconData icon, String title, Color backgroundColor,) {
    return TextButton(
                      onPressed: () {}, 
                      style: TextButton.styleFrom(
                        backgroundColor: backgroundColor,
                        primary: Colors.white,
                        shape: RoundedRectangleBorder(
                          borderRadius: BorderRadius.circular(20),
                        ),
                        side:BorderSide(
                          width: 1.5,
                          color: Colors.white
                        ),
                        minimumSize: Size(140, 40)
                      ),

                      child: Row(
                        children: [
                          Icon(
                            icon,
                            color: Colors.white,
                            size: 22,
                          ),
                          SizedBox(width: 10,),
                          Text(
                            title,
                            style: TextStyle(
                              color: Colors.white,
                              fontFamily: 'baloo da 2',
                              fontSize: 18
                            ),
                          )
                        ],
                      )
                    );
  }

  Widget buidTextField(
      IconData icon, String labelText, String hintText, bool isPassword, bool isEmail, TextEditingController controller, Function validator) {
    return Form(
      child: Padding(
      padding: const EdgeInsets.only(bottom: 8.0),
      child: Column(
        children:[
          TextFormField(
          validator: validator,
          controller: controller,
          obscureText: isPassword,
          keyboardType: isEmail? TextInputType.emailAddress : TextInputType.text,
          decoration: InputDecoration(
              prefixIcon: Icon(
                icon,
                color: Colors.black,
              ),
              enabledBorder: OutlineInputBorder(
                  borderRadius: BorderRadius.circular(15),
                  borderSide: BorderSide(color: Colors.black)),
              focusedBorder: OutlineInputBorder(
                  borderRadius: BorderRadius.circular(15),
                  borderSide: BorderSide(color: Colors.black)),
              labelText: labelText,
              labelStyle: TextStyle(fontFamily: 'raleway'),
              hintText: hintText,
              hintStyle: TextStyle(
                fontSize: 14.0,
                fontFamily: 'raleway',
              ),
              contentPadding: EdgeInsets.all(10)),
        ),
        ] 
      ),
    ),);
  }
}
1 Answers

initialize your form key like this

  final GlobalKey<FormState> _formkey = GlobalKey<FormState>();
Related