You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter表单错误文本位置调整:移至输入框下方的实现方案

实现Flutter表单错误文本显示在输入框下方

问题描述

需要将注册表单的错误文本调整至输入框(带背景的padding box)正下方,参考效果为错误文本与输入框左对齐,显示在背景容器的下方区域。

解决方案

原代码中用固定高度的Container包裹TextFormField,导致错误文本被容器截断或无法显示在外部。修改核心是移除容器固定高度,让布局自适应内容,同时调整输入框装饰样式确保错误文本正确展示。

修改后的完整代码

import 'dart:ui';

import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:form_field_validator/form_field_validator.dart';
import 'package:inventory_app/models/profiles.dart';
import 'package:inventory_app/pallete.dart';
import 'package:inventory_app/screens/screens.dart';
import 'package:inventory_app/widgets/widgets.dart';

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

  @override
  State<CreateNewAccount> createState() => _CreateNewAccountState();
}

class _CreateNewAccountState extends State<CreateNewAccount> {
  final formKey = GlobalKey<FormState>();
  Profile profile = Profile();

  @override
  Widget build(BuildContext context) {
    Size size = MediaQuery.of(context).size;
    return Stack(
      children: [
        BackgroundImage(image: 'assets/images/1167.png'),
        Scaffold(
          backgroundColor: Colors.transparent,
          body: SingleChildScrollView(
            child: Column(
              children: [
                SizedBox(
                  height: size.height * 0.1,
                ),
                Stack(
                  children: [
                    Center(
                      child: ClipOval(
                        child: BackdropFilter(
                          filter: ImageFilter.blur(sigmaX: 3, sigmaY: 3),
                          child: CircleAvatar(
                            radius: size.width * 0.03,
                            backgroundColor: Colors.grey[400]?.withOpacity(0.4),
                            child: Icon(FontAwesomeIcons.user,
                                color: kWhite, size: size.width * 0.03),
                          ),
                        ),
                      ),
                    ),
                    Positioned(
                      top: size.height * 0.02,
                      left: size.width * 0.50,
                      child: Container(
                        height: size.height * 0.05,
                        width: size.width * 0.05,
                        decoration: BoxDecoration(
                            color: kBlue,
                            shape: BoxShape.circle,
                            border: Border.all(color: kWhite, width: 2)),
                        child: Icon(
                          FontAwesomeIcons.arrowUp,
                          color: kWhite,
                        ),
                      ),
                    ),
                  ],
                ),
                SizedBox(
                  height: size.height * 0.1,
                ),
                Form(
                  key: formKey,
                  child: Column(
                    children: [
                      Padding(
                        padding: const EdgeInsets.symmetric(vertical: 10),
                        child: Container(
                          // 移除固定高度,改用padding控制上下间距
                          width: size.width * 0.3,
                          padding: EdgeInsets.symmetric(vertical: size.height * 0.015),
                          decoration: BoxDecoration(
                            color: Colors.green[200]?.withOpacity(0.5),
                            borderRadius: BorderRadius.circular(16),
                          ),
                          child: TextFormField(
                            decoration: InputDecoration(
                              border: InputBorder.none,
                              prefixIcon: Padding(
                                padding: const EdgeInsets.symmetric(
                                    horizontal: 20),
                                child: Icon(
                                  FontAwesomeIcons.envelope,
                                  size: 28,
                                  color: kWhite,
                                ),
                              ),
                              hintText: 'Email-Register',
                              hintStyle: kBodyText,
                              // 调整输入框内部内容的padding
                              contentPadding: EdgeInsets.symmetric(vertical: 0),
                              // 设置错误文本样式,确保显示在容器下方
                              errorStyle: TextStyle(
                                color: Colors.red,
                                fontSize: 12,
                                backgroundColor: Colors.transparent,
                              ),
                            ),
                            style: kBodyText,
                            keyboardType: TextInputType.emailAddress,
                            onSaved: (String? emails) {
                              profile.emails = emails;
                            },
                            validator: MultiValidator([
                              RequiredValidator(
                                  errorText: "Please Enter Your Email !"),
                              EmailValidator(
                                  errorText:
                                      "Please Enter It As The Email Form !"),
                            ]),
                            textInputAction: TextInputAction.next,
                          ),
                        ),
                      ),
                      Padding(
                        padding: const EdgeInsets.symmetric(vertical: 10),
                        child: Container(
                          // 移除固定高度,改用padding控制上下间距
                          width: size.width * 0.3,
                          padding: EdgeInsets.symmetric(vertical: size.height * 0.015),
                          decoration: BoxDecoration(
                            color: Colors.green[200]?.withOpacity(0.5),
                            borderRadius: BorderRadius.circular(16),
                          ),
                          child: TextFormField(
                            decoration: InputDecoration(
                              border: InputBorder.none,
                              prefixIcon: Padding(
                                padding:
                                    const EdgeInsets.symmetric(horizontal: 20),
                                child: Icon(
                                  FontAwesomeIcons.lock,
                                  size: 28,
                                  color: kWhite,
                                ),
                              ),
                              hintText: "Password-Register",
                              hintStyle: kBodyText,
                              // 调整输入框内部内容的padding
                              contentPadding: EdgeInsets.symmetric(vertical: 0),
                              // 设置错误文本样式
                              errorStyle: TextStyle(
                                color: Colors.red,
                                fontSize: 12,
                                backgroundColor: Colors.transparent,
                              ),
                            ),
                            obscureText: true,
                            style: kBodyText,
                            keyboardType: TextInputType.name,
                            onSaved: (String? passwords) {
                              profile.passwords = passwords;
                            },
                            validator: RequiredValidator(
                                errorText: "Please Enter Your Password !"),
                            textInputAction: TextInputAction.next,
                          ),
                        ),
                      ),
                      SizedBox(
                        height: 25,
                      ),
                      Container(
                        height: size.height * 0.08,
                        width: size.width * 0.2,
                        decoration: BoxDecoration(
                          borderRadius: BorderRadius.circular(16),
                          color: Colors.blue[200],
                        ),
                        child: FloatingActionButton(
                          onPressed: () async {
                            if (formKey.currentState!.validate()) {
                              formKey.currentState?.save();
                              try {
                                await FirebaseAuth.instance
                                    .createUserWithEmailAndPassword(
                                        email: profile.emails!,
                                        password: profile.passwords!)
                                    .then((value) {
                                  formKey.currentState?.reset();
                                  Fluttertoast.showToast(
                                    msg: "Register Finished",
                                    gravity: ToastGravity.CENTER,
                                  );
                                  Navigator.pushReplacement(context,
                                      MaterialPageRoute(builder: (context) {
                                    return LoginScreen();
                                  }));
                                });
                              } on FirebaseAuthException catch (e) {
                                print(e.code);
                                String? message;
                                if (e.code == 'email-already-in-use') {
                                  message = "This Email Is Already Registered";
                                } else if (e.code == "weak-password") {
                                  message =
                                      "Password Should More Than 6 Letters";
                                } else {
                                  message = e.message;
                                }
                                Fluttertoast.showToast(
                                  msg: message!,
                                  gravity: ToastGravity.CENTER,
                                );
                              }
                            }
                          },
                          backgroundColor: Colors.cyan[200]?.withOpacity(0.5),
                          child: Text(
                            "Register",
                            style: kBodyText,
                          ),
                        ),
                      ),
                      SizedBox(
                        height: 30,
                      ),
                      Row(
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: [
                          Text("Already have an account?", style: kBodyText),
                          GestureDetector(
                            onTap: () {
                              Navigator.pushNamed(context, '/');
                            },
                            child: Text("  Login",
                                style: kBodyText.copyWith(
                                    color: kBlue, fontWeight: FontWeight.bold)),
                          ),
                        ],
                      ),
                      SizedBox(
                        height: 40,
                      )
                    ],
                  ),
                ),
              ],
            ),
          ),
        ),
      ],
    );
  }
}

关键修改点

  1. 移除容器固定高度:删除每个输入框容器的height属性,改用padding: EdgeInsets.symmetric(vertical: size.height * 0.015)控制输入框上下内边距,让容器自适应内容高度,为错误文本留出显示空间。
  2. 调整输入框内部padding:设置contentPadding: EdgeInsets.symmetric(vertical: 0),避免输入框内容和容器padding重复导致高度冗余。
  3. 配置错误文本样式:通过errorStyle指定错误文本的颜色、字体大小,设置backgroundColor: Colors.transparent确保错误文本显示在容器背景下方,不被遮挡。

内容的提问来源于stack exchange,提问作者Phuris SOMKAEW

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 20:02:34