I am working on the sign up page for me app, I have set it up to have focusnodes for each TextFormField so the user can click on the next button on keyboard to focus next field. The problem is when the page load it focuses on the bottom field even though I have the top "name" field set to autofocus.
I even try to request focus both in the onInit and I've tired right at the top of the build section.
class _SignUpScreenState extends State<SignUpScreen> {
final _signUpFormKey = GlobalKey<FormState>();
final TextEditingController _nameController = TextEditingController();
final TextEditingController _emailController = TextEditingController();
final TextEditingController _passwordController = TextEditingController();
final _authController = Get.find<AuthController>();
late FocusNode _nameFocus, _emailFocus, _passwordFocus, _passwordConfirmFocus;
bool _isLoading = false;
@override
void initState() {
super.initState();
_nameFocus = FocusNode(debugLabel: 'Name Focus');
_emailFocus = FocusNode(debugLabel: 'Email Focus');
_passwordFocus = FocusNode(debugLabel: 'PW Focus');
_passwordConfirmFocus = FocusNode(debugLabel: 'CPW Focus');
_nameFocus.requestFocus();
}
@override
void dispose() {
_nameController.dispose();
_emailController.dispose();
_passwordController.dispose();
_nameFocus.dispose();
_emailFocus.dispose();
_passwordFocus.dispose();
_passwordConfirmFocus.dispose();
super.dispose();
}
// Sign-up form Section
Widget buildSignUpForm() {
return Form(
key: _signUpFormKey,
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
RoundedTextFormField(
autoFocus: true,
focusNode: _nameFocus,
onFieldSubmitted: _fieldFocusChange(context, _nameFocus, _emailFocus),
keyboardType: TextInputType.name,
keyboardAction: TextInputAction.next,
controller: _nameController,
hintText: 'Name',
validator: (value) {
if (value.toString().length <= 2 || value!.isEmpty) {
return 'Enter a valid Name';
}
return null;
},
),
SizedBox(height: 10.h),
RoundedTextFormField(
focusNode: _emailFocus,
onFieldSubmitted: _fieldFocusChange(context, _emailFocus, _passwordFocus),
keyboardType: TextInputType.emailAddress,
keyboardAction: TextInputAction.next,
controller: _emailController,
hintText: 'Email',
validator: (email) => email != null && !EmailValidator.validate(email) ? 'Enter a valid email' : null,
),
SizedBox(height: 10.h),
RoundedTextFormField(
focusNode: _passwordFocus,
onFieldSubmitted: _fieldFocusChange(context, _passwordFocus, _passwordConfirmFocus),
keyboardType: TextInputType.visiblePassword,
keyboardAction: TextInputAction.next,
obsecureText: true,
controller: _passwordController,
hintText: 'Password',
validator: (value) {
if (value.toString().length < 6 || value!.isEmpty) {
return 'Password should be longer or equal to 6 characters.';
}
return null;
},
),
SizedBox(height: 10.h),
RoundedTextFormField(
focusNode: _passwordConfirmFocus,
keyboardAction: TextInputAction.done,
onFieldSubmitted: (_) {
Utilities.logInfo('Signup Submit button Pressed');
if (_signUpFormKey.currentState!.validate()) {
_signUpFormKey.currentState!.save();
setState(() {
_isLoading = true;
});
FocusScope.of(context).unfocus();
String name = _nameController.text.trim();
String email = _emailController.text.trim();
String password = _passwordController.text.trim();
Utilities.logInfo('Attempting Signup with Firebase');
_authController.signUpWithEmail(name, email, password);
setState(() {
_isLoading = false;
});
}
},
keyboardType: TextInputType.visiblePassword,
obsecureText: true,
hintText: 'Confirm Password',
validator: (value) {
if (value!.trim() != _passwordController.text.trim() || value.isEmpty) {
return 'Passwords do not match!';
}
return null;
},
),
SizedBox(height: 10.h),
_isLoading
? const CircularProgressIndicator() // TODO custom progress indicator
: ElevatedButton(
buttonText: 'Sign Up',
onPressed: () {
Utilities.logInfo('Signup Submit button Pressed');
if (_signUpFormKey.currentState!.validate()) {
_signUpFormKey.currentState!.save();
setState(() {
_isLoading = true;
});
FocusScope.of(context).unfocus();
String name = _nameController.text.trim();
String email = _emailController.text.trim();
String password = _passwordController.text.trim();
Utilities.logInfo('Attempting Signup with Firebase');
_authController.signUpWithEmail(name, email, password);
setState(() {
_isLoading = false;
});
}
},
),
SizedBox(height: 10.h),
],
),
);
}
and I have this method to change focus nodes
_fieldFocusChange(BuildContext context, FocusNode currentFocus, FocusNode nextFocus) {
currentFocus.unfocus();
FocusScope.of(context).requestFocus(nextFocus);
}
So when page loads it automatically focuses the confirm password field. I have also commented out the confirmPassword field so its just the 3 fields and then nothing gets focused when page loads. I'm a little confused why the autofocus doesnt work on the nameFocus field though.
Any help would be most appreciated.