Home > Mobile >  Why doesn't the email text field have focus?
Why doesn't the email text field have focus?

Time:01-23

My code writes the code where the email textfield needs to be focused. However, when I change the screen to the signup screen and back, the email textfield is not focused.

Here are two videos showing what I said:

Email textfield

Keyboard

As you can see, when I open the sign in screen, the keyboard pops up. When I change the screen to the sign up screen, the keyboard also pops up. However, when I change back to the sign in screen, there is no keyboard, but the email text field is weird:

Email textfield

Keyboard

Why is this result returned?

My code:

enum SignInFormType { signIn, signUp }

class SignInState {
  SignInState({
    this.isSubmitted = false,
    this.isPasswordObscured = true,
    this.formType = SignInFormType.signIn,
    this.value = const AsyncValue.data(null),
  });

  final bool isSubmitted;
  final bool isPasswordObscured;
  final SignInFormType formType;

  final AsyncValue<void> value;

  bool get isLoading => value.isLoading;

  SignInState copyWith({
    bool? isSubmitted,
    bool? isPasswordObscured,
    SignInFormType? formType,
    AsyncValue<void>? value,
  }) {
    return SignInState(
      isSubmitted: isSubmitted ?? this.isSubmitted,
      isPasswordObscured: isPasswordObscured ?? this.isPasswordObscured,
      formType: formType ?? this.formType,
      value: value ?? this.value,
    );
  }
}

extension SignInScreenState on SignInState {
  String? nameValidator(String? value) {
    if (value!.trim().isEmpty) {
      return "Please enter your name";
    }
    return null;
  }

  String? emailValidator(String? value) {
    if (value!.trim().isEmpty) {
      return "Please enter your email address";
    }
    if (!RegExp(r"\S @\S \.\S ").hasMatch(value)) {
      return "Please enter a valid email address";
    }
    return null;
  }

  String get title {
    if (formType == SignInFormType.signIn) {
      return "Sign in";
    } else {
      return "Sign up";
    }
  }

  String get secondaryButtonText {
    if (formType == SignInFormType.signIn) {
      return "Sign up";
    } else {
      return "Sign in";
    }
  }

  SignInFormType get secondaryActionFormType {
    if (formType == SignInFormType.signUp) {
      return SignInFormType.signIn;
    } else {
      return SignInFormType.signUp;
    }
  }
}

class SignInController extends StateNotifier<SignInState> {
  SignInController({required SignInFormType formType}) : super(SignInState(formType: formType));

  void updateIsSubmitted(bool isSubmitted) => state = state.copyWith(isSubmitted: isSubmitted);

  void updateIsPasswordObscured(bool isPasswordObscured) => state = state.copyWith(isPasswordObscured: isPasswordObscured);

  void updateFormType(SignInFormType formType) {
    state = state.copyWith(formType: formType);
  }
}

final signInControllerProvider = StateNotifierProvider.autoDispose.family<SignInController, SignInState, SignInFormType>(
  (ref, formType) => SignInController(formType: formType);
);

class CustomTextFormField extends StatelessWidget {
  const CustomTextFormField({
    this.focusNode,
    this.textFormFieldKey,
    this.controller,
    this.validator,
    this.icon,
    required this.labelText,
    required this.hintText,
    this.suffixIcon,
    this.obscureText,
    this.keyboardType,
    this.textInputAction,
    required this.readOnly,
    this.maxLines,
    this.onEditingComplete,
    this.enabled,
    this.onChanged,
    this.onFieldSubmitted,
    this.onSaved,
    this.onTap,
    this.initialValue,
    this.autofocus,
    super.key,
  });

  final FocusNode? focusNode;
  final Key? textFormFieldKey;
  final TextEditingController? controller;
  final String? Function(String?)? validator;
  final IconData? icon;
  final String labelText;
  final String hintText;
  final Widget? suffixIcon;
  final bool? obscureText;
  final TextInputType? keyboardType;
  final TextInputAction? textInputAction;
  final bool readOnly;
  final int? maxLines;
  final VoidCallback? onEditingComplete;
  final bool? enabled;
  final Function(String)? onChanged;
  final Function(String)? onFieldSubmitted;
  final Function(String?)? onSaved;
  final VoidCallback? onTap;
  final String? initialValue;
  final bool? autofocus;

  @override
  Widget build(BuildContext context) => Theme(
        data: ThemeData().copyWith(colorScheme: ThemeData().colorScheme.copyWith(primary: Colors.black.withOpacity(0.5))),
        child: TextFormField(
          autofocus: autofocus ?? false,
          focusNode: focusNode,
          key: textFormFieldKey,
          controller: controller,
          validator: validator,
          style: const TextStyle(color: Colors.black),
          textAlignVertical: TextAlignVertical.top,
          initialValue: initialValue,
          decoration: InputDecoration(
            alignLabelWithHint: true,
            floatingLabelAlignment: FloatingLabelAlignment.start,
            prefixIcon: icon == null ? null : Icon(icon, color: Colors.black),
            labelText: labelText,
            labelStyle: const TextStyle(color: Colors.black),
            hintText: hintText,
            hintStyle: const TextStyle(color: Colors.black),
            border: const OutlineInputBorder(),
            focusedBorder: const OutlineInputBorder(borderSide: BorderSide(color: Colors.black, width: 1.0)),
            enabledBorder: const OutlineInputBorder(borderSide: BorderSide(color: Colors.black, width: 1.0)),
            suffixIcon: suffixIcon,
            filled: true,
            fillColor: Colors.white,
          ),
          autocorrect: false,
          obscureText: obscureText == null ? false : obscureText!,
          keyboardType: keyboardType,
          textInputAction: textInputAction,
          readOnly: readOnly,
          maxLines: maxLines,
          onEditingComplete: onEditingComplete,
          enabled: enabled,
          onChanged: onChanged,
          onFieldSubmitted: onFieldSubmitted,
          onSaved: onSaved,
          onTap: onTap,
        ),
      );
}
class SignInScreen extends ConsumerStatefulWidget {
  const SignInScreen({required this.formType, super.key});

  final SignInFormType formType;

  @override
  ConsumerState<SignInScreen> createState() => _SignInScreenState();
}

class _SignInScreenState extends ConsumerState<SignInScreen> {
  final formKey = GlobalKey<FormState>();

  final emailFocusNode = FocusNode();
  final nameFocusNode = FocusNode();

  final nameController = TextEditingController();
  final emailController = TextEditingController();
  final passwordController = TextEditingController();

  void updateFormType(SignInFormType formType) {
    ref.read(signInControllerProvider(widget.formType).notifier).updateFormType(formType);

    passwordController.clear();
  }

  @override
  void initState() {
    emailFocusNode.requestFocus();
    super.initState();
  }

  @override
  void dispose() {
    nameFocusNode.dispose();
    emailFocusNode.dispose();
    nameController.dispose();
    emailController.dispose();
    passwordController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final state = ref.watch(signInControllerProvider(widget.formType));
    final controller = ref.read(signInControllerProvider(widget.formType).notifier);

    return Scaffold(
      appBar: AppBar(title: Text(state.title)),
      body: Padding(
        padding: const EdgeInsets.all(10.0),
        child: Form(
          key: formKey,
          child: SingleChildScrollView(
            child: Column(
              children: [
                state.secondaryActionFormType == SignInFormType.signUp
                    ? Container()
                    : CustomTextFormField(
                        focusNode: nameFocusNode,
                        controller: nameController,
                        validator: (value) => state.nameValidator(value),
                        icon: FontAwesomeIcons.solidUser,
                        labelText: "Name",
                        hintText: "Type your name here...",
                        keyboardType: TextInputType.name,
                        textInputAction: TextInputAction.next,
                        readOnly: state.isSubmitted ? true : false,
                      ),
                state.secondaryActionFormType == SignInFormType.signUp ? Container() : const SizedBox(height: 10.0),
                CustomTextFormField(
                  focusNode: emailFocusNode,
                  controller: emailController,
                  validator: (value) => state.emailValidator(value),
                  icon: Icons.email,
                  labelText: "Email",
                  hintText: "Type your email here...",
                  keyboardType: TextInputType.emailAddress,
                  textInputAction: TextInputAction.next,
                  readOnly: state.isSubmitted,
                ),
                …
                InkWell(
                  onTap: state.isSubmitted == true
                      ? null
                      : () {
                          updateFormType(state.secondaryActionFormType);
                          if (state.formType == signInFormType.signIn) {
                            emailFocusNode.unfocus();
                            nameFocusNode.requestFocus();
                          } else {
                            nameFocusNode.unfocus();
                            emailFocusNode.requestFocus();
                          }
                        },
                  child: Text(state.secondaryButtonText, textAlign: TextAlign.center, style: const TextStyle(color: Colors.black)),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

Feel free to leave a comment if you need more information.

Why doesn't the email text field have focus? I would appreciate any help. Thank you in advance!

CodePudding user response:

I solved your problem using autofocus.. Below the code..

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:rezar_app/views/bin/home_view.dart';
import 'package:rezar_app/views/homeViewFlow/home_view.dart';

class BinFile extends StatefulWidget {
const BinFile({super.key});

@override
State<BinFile> createState() => _BinFileState();
}

 class _BinFileState extends State<BinFile> {
 @override
   Widget build(BuildContext context) {
  return Scaffold(
  appBar: AppBar(title: Text('Login View')),
  body: Column(
    children: [
      CustomTextFormField(
          labelText: 'Email',
          hintText: 'Enter Mail',
          readOnly: false,
          autofocus: true),
      CustomTextFormField(
          labelText: 'Password',
          hintText: 'Enter Password',
          readOnly: false),
      SizedBox(
        height: 10,
      ),
      SizedBox(
        height: 10,
      ),
      ElevatedButton(
          onPressed: () {
            Get.to(() => HomeNewScreen());
          },
          child: Text('Next Page'))
    ],
  ),
);
     }
     }

 class CustomTextFormField extends StatelessWidget {
  const CustomTextFormField({
this.focusNode,
this.textFormFieldKey,
this.controller,
this.validator,
this.icon,
required this.labelText,
required this.hintText,
this.suffixIcon,
this.obscureText,
this.keyboardType,
this.textInputAction,
required this.readOnly,
this.maxLines,
this.onEditingComplete,
this.enabled,
this.onChanged,
this.onFieldSubmitted,
this.onSaved,
this.onTap,
this.initialValue,
this.autofocus,
super.key,
  });

  final FocusNode? focusNode;
     final Key? textFormFieldKey;
    final TextEditingController? controller;
   final String? Function(String?)? validator;
 final IconData? icon;
  final String labelText;
 final String hintText;
   final Widget? suffixIcon;
  final bool? obscureText;
   final TextInputType? keyboardType;
   final TextInputAction? textInputAction;
   final bool readOnly;
    final int? maxLines;
    final VoidCallback? onEditingComplete;
  final bool? enabled;
  final Function(String)? onChanged;
   final Function(String)? onFieldSubmitted;
   final Function(String?)? onSaved;
   final VoidCallback? onTap;
    final String? initialValue;
   final bool? autofocus;

    @override
    Widget build(BuildContext context) => Theme(
    data: ThemeData().copyWith(
        colorScheme: ThemeData()
            .colorScheme
            .copyWith(primary: Colors.black.withOpacity(0.5))),
    child: TextFormField(
      autofocus: autofocus ?? false,
      focusNode: focusNode,
      key: textFormFieldKey,
      controller: controller,
      validator: validator,
      style: const TextStyle(color: Colors.black),
      textAlignVertical: TextAlignVertical.top,
      initialValue: initialValue,
      decoration: InputDecoration(
        alignLabelWithHint: true,
        floatingLabelAlignment: FloatingLabelAlignment.start,
        prefixIcon: icon == null ? null : Icon(icon, color: Colors.black),
        labelText: labelText,
        labelStyle: const TextStyle(color: Colors.black),
        hintText: hintText,
        hintStyle: const TextStyle(color: Colors.black),
        border: const OutlineInputBorder(),
        focusedBorder: const OutlineInputBorder(
            borderSide: BorderSide(color: Colors.black, width: 1.0)),
        enabledBorder: const OutlineInputBorder(
            borderSide: BorderSide(color: Colors.black, width: 1.0)),
        suffixIcon: suffixIcon,
        filled: true,
        fillColor: Colors.white,
      ),
      autocorrect: false,
      obscureText: obscureText == null ? false : obscureText!,
      keyboardType: keyboardType,
      textInputAction: textInputAction,
      readOnly: readOnly,
      maxLines: maxLines,
      onEditingComplete: onEditingComplete,
      enabled: enabled,
      onChanged: onChanged,
      onFieldSubmitted: onFieldSubmitted,
      onSaved: onSaved,
      onTap: onTap,
    ),
  );
    }

Second Screen below the code

import 'package:flutter/material.dart';

class HomeNewScreen extends StatefulWidget {
const HomeNewScreen({super.key});

@override
State<HomeNewScreen> createState() => _HomeNewScreenState();
}

class _HomeNewScreenState extends State<HomeNewScreen> {
@override
Widget build(BuildContext context) {
return Scaffold(
  body: Center(child: Text('Home Screen')),
 );
  }
  }

CodePudding user response:

Please try two solution

  1. remove readOnly in emailTextField either
  2. readOnly: false
  • Related