简体   繁体   English

Flutter Textformfield 错误消息下移下一个小部件

[英]Flutter Textformfield error message shifted down the next widget

I have an issue with my textformfield.我的文本表单字段有问题。 Whenever the error message shows, it shifted down the next widget below...每当显示错误消息时,它就会向下移动下面的下一个小部件...

I try to search how to give a placement for the error text to no take a placement that does not exist when it is not shown, but I didn't find the solution.我尝试搜索如何为错误文本提供位置,以便在未显示时不使用不存在的位置,但我没有找到解决方案。

Here are the screenshot and the code of the issue.这是问题的屏幕截图和代码。

在此处输入图像描述

class AuthForm extends StatefulWidget {
  final bool isPassword;
  final IconData prefixIcon;
  final String hintText;
  late bool isPasswordVisible = isPassword;
  final bool isCalendar;
  final TextEditingController controller;
  final bool isDropDown;
  final bool isPhone;
  final String? Function(String?)? validator;

  AuthForm({Key? key, this.isPassword = false, required this.prefixIcon, required this.hintText,
    this.isCalendar = false, required this.controller, this.isDropDown = false, this.isPhone = false, required this.validator}) : super(key: key);

  @override
  State<AuthForm> createState() => _AuthFormState();
}

class _AuthFormState extends State<AuthForm> {

  @override
  void initState() {
    super.initState();
    if (widget.isPhone){
      getCountryCode();
    }
  }

  start () async {
    await CountryCodes.init();
  }
  Locale? getCountryCode () {
    start();
    final Locale? deviceLocale = CountryCodes.getDeviceLocale();
    final CountryDetails details = CountryCodes.detailsForLocale();
    return deviceLocale;
  }

  DateTime selectedDate = DateTime(2000,1);
  Future<void> _selectDate(BuildContext context) async {
    final DateTime? picked = await showDatePicker(
        context: context,
        initialDate: selectedDate,
        firstDate: DateTime(1950, 1),
        lastDate: DateTime.now());
    if (picked != null && picked != selectedDate) {
      setState(() {
        selectedDate = picked;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return widget.isDropDown ? const DropDownBar() :
    SizedBox(
      width: 70.w,
      child: TextFormField(
          validator: widget.validator,
          keyboardType: widget.isPhone ? TextInputType.phone : TextInputType.text,
          inputFormatters: [DialCodeFormatter()],
          controller: widget.controller,
          textAlign: TextAlign.center,
          obscureText: widget.isPasswordVisible,
          style: Theme.of(context).textTheme.bodyText2,
          decoration: InputDecoration(
            contentPadding: EdgeInsets.fromLTRB(0, 2.3.h, 0, 0),
            hintText : widget.hintText,
            hintStyle: Theme.of(context).textTheme.bodyText1,
            enabledBorder: UnderlineInputBorder(
              borderSide: BorderSide(
                color: Theme.of(context).splashColor,
                width: 0.13.w,
              ),
            ),
            errorStyle: Theme.of(context).textTheme.headline6,
            prefixIcon: Container(
              width: 0,
              alignment: const Alignment(-0.99, 0.5),
              child: Icon(
                widget.prefixIcon,
                color: Theme.of(context).primaryColor,
                size: 6.w,
              ),
            ),
            suffixIcon: Visibility(
              visible: widget.isPassword,
              //Maintain the space where the widget is even if it is hid
              maintainAnimation: true,
              maintainState: true,
              maintainSize: true,
              child: InkWell(
                highlightColor : Colors.transparent,
                splashColor: Colors.transparent,
                child: Container(
                  width: 0,
                  alignment: const Alignment(0.99, 0.5),
                  child: Icon(
                    widget.isPasswordVisible ? Icons.visibility : Icons.visibility_off,
                    color: Theme.of(context).primaryColor,
                    size: 6.w,
                  ),
                ),
                onTap: () {
                  setState(() {
                    widget.isPasswordVisible = !widget.isPasswordVisible;
                  });
                },
              ),
            ),
          ),
          onTap: () async {
            if (widget.isCalendar){
              //Dismiss the keyboard
              FocusScope.of(context).requestFocus(FocusNode());
              //Call the calendar
              await _selectDate(context);
              widget.controller.text = DateFormat('dd-MM-yyyy').format(selectedDate);
            }
          }
      ),
    );
  }
}

Login Page登录页面

@override
  Widget build(BuildContext context) {
    return BlocListener<InternetCubit, InternetState>(
      listener: (context, state) {
        if (state is InternetDisconnected) {
          showAlertBox(context);
        }
      },
    child: Form(
      key: _formkey,
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          SizedBox(
            height: 6.h,
          ),
          Text(
            "Flexmes",
            style: Theme.of(context).textTheme.headline1,
          ),
          SizedBox(
            height: 8.h,
          ),
          AuthForm(
            prefixIcon: Icons.email_outlined,
            hintText: "Email",
            controller: emailController,
            nextFocusNode: passwordNode,
            validator: MultiValidator([
              RequiredValidator(errorText: 'Email is required'),
              EmailValidator(errorText: 'Enter a valid email address'),
            ]),
          ),
          SizedBox(
            height: 3.h,
          ),
          AuthForm(
            isPassword: true,
            prefixIcon: Icons.lock_rounded,
            hintText: "Password",
            controller: passwordController,
            currentFocusNode: passwordNode,
            validator: MultiValidator([
              RequiredValidator(errorText: 'Password is required'),
              MinLengthValidator(6, errorText: 'Password must be at least 6 digits long'),
              PatternValidator(r'(?=.*?[#?!@$%^&*-])', errorText: 'Passwords must have at least one special character')
            ]),
          ),
          SizedBox(
            height: 4.5.h,
          ),
          SizedBox(
            width: 70.w,
            child: Row(
              mainAxisAlignment: MainAxisAlignment.start,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: [
                CustomCheckbox(
                  iconColor: Colors.black,
                  activeColor: const Color.fromARGB(255, 3, 218, 197),
                ),
                SizedBox(
                  width: 3.w,
                ),
                Text(
                  "Remember me",
                  style: Theme.of(context).textTheme.bodyText2,
                )
              ],
            ),
          ),
          SizedBox(
            height: 4.5.h,

          ),
          AuthButton(
            text: "Log In",
            onPressed: (){
              if (isInternetDisconnected(context)){
                showAlertBox(context);
              } else{
                if (_formkey.currentState!.validate()){
                  AuthenticationAPI(auth: FirebaseAuth.instance).signInWithEmail(emailController.text, passwordController.text);
                  //return navigation
                }

              }
            }
          ),
          SizedBox(
            height: 3.2.h,
          ),
          ClickableText(
            text: "Forgot Password ?",
            onPressed: () {
              if (isInternetDisconnected(context)){
                showAlertBox(context);
              } else{
                //return navigation
              }
            },
          ),
          SizedBox(
            height: 3.2.h,
          ),
          const AuthDivider(
            text: "OR",
          ),
          SizedBox(
            height: 2.h,
          ),
          SizedBox(
            width: 70.w,
            child: Row(
              crossAxisAlignment: CrossAxisAlignment.center,
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                ClickableImage(
                  imagePath: "assets/images/icon/Facebook.png",
                  width: 23.w,
                  onPressed: () {
                    null;
                  },
                ),
                ClickableImage(
                  imagePath: "assets/images/icon/Instagram.png",
                  width: 23.w,
                  onPressed: () {
                    null;
                  },
                ),
                ClickableImage(
                  imagePath: "assets/images/icon/Tiktok.png",
                  width: 23.w,
                  onPressed: () {
                    null;
                  },
                ),
              ],
            ),
          ),
          SizedBox(
            height: 4.h,
          ),
          SizedBox(
            width: 70.w,
            child: Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Text(
                  "Don't have an account ? ",
                  style: Theme.of(context).textTheme.bodyText2,
                ),
                ClickableText(
                  text: 'Sign up Now !',
                  onPressed: () {
                    if (isInternetDisconnected(context)){
                      showAlertBox(context);
                    } else{
                      Navigator.of(context).pushNamed("/signup1");
                    }
                  },
                ),
              ],
            ),
          ),
        ],
      ),
    ),
);
  }
}

Thanks for your suggestion,谢谢你的建议,

Chris克里斯

try wrapping textformfield with container and giving it height and width尝试用容器包装 textformfield 并给它高度和宽度

Try wrapping TextFormField with container and give it height and width.尝试用容器包装 TextFormField 并为其指定高度和宽度。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM