I have a registration screen with the form at the bottom of the screen, and I want to make it so that the whole form goes up when any text field is tapped, for some reason only the very last one does that. However, i am also faced with another problem.. My UI kind of swallows up the form that goes up? I want the white part to expand along with the form so that it takes up the whole screen basically..
Here is my code:
return MaterialApp(
home: Scaffold(
//resizeToAvoidBottomInset: true,
backgroundColor: backGroundPink,
// backgroundColor: whiteColor,
body: SafeArea(
child: Form(
key: _formKey,
child: Column(
children: [
const SizedBox(height: 45.0),
Container(
height: 100,
child: Text(
"Get Started",
style: TextStyle(
color: Color(0xFFD77D7C),
fontSize: 38,
fontFamily: 'Urbanist',
fontWeight: FontWeight.w700,
height: 1.30,
letterSpacing: -0.28,
),
),
),
// const SizedBox(height: 10.0),
Expanded(
child: Container(
padding: const EdgeInsets.only(
left: 22.0,
right: 22,
top: 5.0,
bottom: 5,
),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.vertical(
top: Radius.circular(80.0) //change this,
),
),
child: SingleChildScrollView(
/* padding: EdgeInsets.only(
bottom:
MediaQuery.of(context).viewInsets.bottom + 100),*/
// physics: NeverScrollableScrollPhysics(),
child: Column(
//mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
const SizedBox(height: 40.0),
Text("Create a Preggo account",
style: TextStyle(
fontSize: 23.0,
fontWeight: FontWeight.w600,
)),
const SizedBox(height: 45.0),
/*const SizedBox(height: 40.0),
Text("Welcome back!",
style: TextStyle(
fontSize: 23.0,
fontWeight: FontWeight.w600,
)),
*/
// const SizedBox(height: 50.0),
Container(
height: 85,
constraints: BoxConstraints(maxHeight: 100),
child: TextFormField(
controller: _usernameController,
key: _usernameKey,
validator: (value) {
/*
username validations:
--FRONT END--
1- not empty
2- no spaces
3- no special characters (only letters and digits)
--BACK END--
4- unique
*/
if (value!.isEmpty == true) {
return "This field cannot be empty.";
} else if (!validCharacters.hasMatch(value)) {
return "Only alphanumerical values allowed."; //maybe change error message
} else if (usernameTaken) {
return 'Username is already taken!';
} else {
return null;
}
},
decoration: InputDecoration(
hintText: "Username",
helperText: '',
labelStyle: const TextStyle(
fontSize: 15,
fontWeight: FontWeight.w500,
color: grayColor,
),
prefixIcon: const Icon(
Icons.person,
color: Colors.grey,
),
filled: true,
fillColor: textFieldBackgroundColor,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12.0),
),
enabledBorder: const OutlineInputBorder(
borderRadius:
BorderRadius.all(Radius.circular(12.0)),
borderSide:
BorderSide(color: textFieldBorderColor),
),
focusedBorder: const OutlineInputBorder(
borderRadius:
BorderRadius.all(Radius.circular(12.0)),
borderSide: BorderSide(color: darkGrayColor),
),
),
),
),
// const SizedBox(height: 22.0),
Container(
height: 85,
constraints: BoxConstraints(maxHeight: 100),
child: TextFormField(
controller: _emailController,
key: _emailKey,
validator: (value) {
if (value!.isEmpty) {
return "This field cannot be empty.";
} else if (!EmailValidator.validate(value)) {
return "Please enter a valid email.";
} else if (emailTaken) {
return 'Email is already taken!';
} else {
return null;
}
},
/*
email validations:
--FRONT END--
1- format: [email protected]
2- only allowed characters of email
3- only 1 @
4- not empty
--BACK END--
5- unique
*/
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
helperText: '',
hintText: "Email",
labelStyle: const TextStyle(
fontSize: 15,
fontWeight: FontWeight.w500,
color: grayColor,
),
prefixIcon: const Icon(
Icons.email,
color: Colors.grey,
),
filled: true,
fillColor: textFieldBackgroundColor,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12.0),
),
enabledBorder: const OutlineInputBorder(
borderRadius:
BorderRadius.all(Radius.circular(12.0)),
borderSide:
BorderSide(color: textFieldBorderColor),
),
focusedBorder: const OutlineInputBorder(
borderRadius:
BorderRadius.all(Radius.circular(12.0)),
borderSide: BorderSide(color: darkGrayColor),
),
),
),
),
Container(
height: 85,
constraints: BoxConstraints(maxHeight: 100),
child: PhoneFormField(
countrySelectorNavigator:
const CountrySelectorNavigator
.searchDelegate(),
autovalidateMode: AutovalidateMode.disabled,
controller: _phoneControllerCC,
key: _phoneKey,
/*
phone number validations
--FRONT END--
1- 10 digits
2- digits only
--BACK END--
3- unique (???)
*/
validator: PhoneValidator.validMobile(),
/* (phone) {
bool hasLetter = false;
int i = 0;
while (i < phone!.toString().length) {
if (!isNumeric(phone.toString().[i])) {
hasLetter = true;
}
i++;
}
if (hasLetter) {
return 'Field must contain only digits.';
}
if (phone.toString().isEmpty) {
return 'This field cannot be empty.';
} else if (phone.toString().length != 10) {
return 'Phone number must be 10 digits.';
} else if (phoneTaken) { !!!!!!!!!!!!!!!!!!!!!!!!!
return 'Phone number is already taken!';
} else {
return null;
}
},*/
keyboardType: TextInputType.phone,
decoration: InputDecoration(
helperText: '',
hintText: "Phone number (optional)",
labelStyle: const TextStyle(
fontSize: 15,
fontWeight: FontWeight.w500,
color: grayColor,
),
/* prefixIcon: const Icon(
Icons.phone,
color: Colors.grey,
),*/
filled: true,
fillColor: textFieldBackgroundColor,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12.0),
),
enabledBorder: const OutlineInputBorder(
borderRadius:
BorderRadius.all(Radius.circular(12.0)),
borderSide:
BorderSide(color: textFieldBorderColor),
),
focusedBorder: const OutlineInputBorder(
borderRadius:
BorderRadius.all(Radius.circular(12.0)),
borderSide: BorderSide(color: darkGrayColor),
),
),
),
),
Container(
height: 85,
constraints: BoxConstraints(maxHeight: 90),
child: TextFormField(
controller: _passwordController,
/*
password validations
1- 8 digits or more
2- at least one capital
3- at least one number
*/
decoration: InputDecoration(
helperText: '',
prefixIcon: const Icon(
Icons.lock,
color: Colors.grey,
),
hintText: 'Password',
labelStyle: const TextStyle(
fontSize: 15,
fontWeight: FontWeight.w500,
color: grayColor,
),
filled: true,
fillColor: textFieldBackgroundColor,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12.0),
),
enabledBorder: const OutlineInputBorder(
borderRadius:
BorderRadius.all(Radius.circular(12.0)),
borderSide:
BorderSide(color: textFieldBorderColor),
),
focusedBorder: const OutlineInputBorder(
borderRadius:
BorderRadius.all(Radius.circular(12.0)),
borderSide: BorderSide(color: darkGrayColor),
),
suffixIcon: GestureDetector(
onTap: () {
setState(() {
hidePassword = !hidePassword;
});
},
child: hidePassword
? const Icon(
Icons.visibility_off,
color: Colors.grey,
)
: const Icon(
Icons.visibility,
color: Colors.grey,
),
),
),
obscureText: hidePassword ? true : false,
autocorrect: false,
validator: (pass) {
if (pass!.isEmpty == true) {
return "This field cannot be empty.";
} else if (pass.length < 8) {
return "Password must be at least 8 characters.";
} else {
bool hasDigit = false;
bool hasUppercase = false;
int i = 0;
while (i < pass.length) {
if (isNumeric(pass[i])) {
hasDigit = true;
} else if (isUppercase(pass[i])) {
hasUppercase = true;
}
i++;
} //end while
if (hasDigit == false ||
hasUppercase == false) {
return "Password must contain at least one uppercase letter nand one digit.";
}
} //end else
return null;
},
),
),
//const SizedBox(height: 45.0),
MaterialButton(
color: darkBlackColor,
minWidth: double.infinity,
height: 48,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(40.0),
),
onPressed: ()
{ },
child: Text(
'Sign Up',
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.w600,
color: whiteColor,
),
),
),
const SizedBox(height: 25.0),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Already have an account? ',
style: Theme.of(context)
.textTheme
.titleLarge
?.copyWith(
fontWeight: FontWeight.normal,
fontSize: 15,
color: blackColor,
),
),
GestureDetector(
onTap: () {
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(
builder: (context) {
return const LoginScreen();
},
), (route) => false);
},
child: Text(
'Log In',
style: Theme.of(context)
.textTheme
.titleLarge
?.copyWith(
fontWeight: FontWeight.w600,
fontSize: 15,
color: pinkColor,
decoration: TextDecoration.underline,
),
),
)
],
),
],
),
),
),
),
],
),
),
),
),
);
}
}
these are pictures of my screen:
my UI with the keyboard pulled up, covering the bottom fields and not expanding the white part
the white part ‘swallowing’ the fields while scrolling the fields
2
Answers
The solution is to set resizeToAvoidBottomInset property to false.
code