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, ) ], ), ), ], ), ), ), ], ); } }
关键修改点
- 移除容器固定高度:删除每个输入框容器的
height属性,改用padding: EdgeInsets.symmetric(vertical: size.height * 0.015)控制输入框上下内边距,让容器自适应内容高度,为错误文本留出显示空间。 - 调整输入框内部padding:设置
contentPadding: EdgeInsets.symmetric(vertical: 0),避免输入框内容和容器padding重复导致高度冗余。 - 配置错误文本样式:通过
errorStyle指定错误文本的颜色、字体大小,设置backgroundColor: Colors.transparent确保错误文本显示在容器背景下方,不被遮挡。
内容的提问来源于stack exchange,提问作者Phuris SOMKAEW
相关产品推荐
相关产品推荐

