Flutter TextFormField验证错误时仅显红边框却上移的问题求助
TextFormField验证错误时上移问题修复(保持尺寸固定+仅错误时红边框)
我需要实现一个TextFormField,仅在验证错误时显示红色边框。目前红边框效果已实现,但出现异常:验证错误触发时输入框会向上偏移。推测是contentPadding属性导致的,移除该属性后偏移消失,但输入框高度会改变。我需要保持输入框的尺寸和位置固定,仅在错误时显示红边框。
原代码
import 'package:beatscore/app/utils/beatscore_colors.dart'; import 'package:beatscore/main.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; // ignore: must_be_immutable class CustomTextField extends StatelessWidget { CustomTextField( {super.key, required this.onMutted, this.placeholder, this.protected = false, this.prefixIcon, this.suffixIcon, this.suffixAction, this.inputFormatters, this.validator, this.controller, this.textInputType, this.errorText}); Icon? prefixIcon; Icon? suffixIcon; bool protected; Function()? suffixAction; Function onMutted; String? placeholder; TextEditingController? controller; String? Function(String)? validator; List<TextInputFormatter>? inputFormatters; TextInputType? textInputType; String? errorText; @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.symmetric( horizontal: 16, vertical: 8, ), child: SizedBox( width: 310, child: TextFormField( keyboardType: textInputType, autovalidateMode: AutovalidateMode.onUserInteraction, validator: validator == null ? null : (value) => validator!(value!), inputFormatters: inputFormatters, onChanged: (value) => onMutted(value), cursorColor: const Color.fromARGB(255, 0, 0, 0), style: const TextStyle( fontSize: 16, color: Color.fromRGBO(30, 30, 30, 0.6), height: 1.6), obscureText: protected, controller: controller, decoration: InputDecoration( errorBorder: const OutlineInputBorder( borderSide: BorderSide(color: BeatscoreColors.ligthErrorRed), ), contentPadding: const EdgeInsets.symmetric( horizontal: 12.5, vertical: 12.5, ), errorText: errorText, hintText: placeholder, prefixIcon: prefixIcon, suffixIcon: suffixIcon != null ? IconButton( icon: suffixIcon!, onPressed: suffixAction, ) : null, focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(8), borderSide: const BorderSide( width: 0, style: BorderStyle.none, )), filled: true, fillColor: Colors.white, border: OutlineInputBorder( borderRadius: BorderRadius.circular(8), borderSide: const BorderSide( width: 0, style: BorderStyle.none, ), ), ), ), ), ); } }
问题原因
输入框上移是因为验证错误时,Flutter会默认给错误文本预留垂直空间,而contentPadding的设置和错误状态下的边框布局冲突,导致整体布局重排。
修复方案
通过以下调整保持输入框尺寸固定,仅在错误时显示红边框:
- 禁用错误文本的空间占用(如果不需要显示错误文本,可直接去掉
errorText属性,依赖validator返回值即可) - 统一错误状态下的边框样式(包括聚焦错误状态),避免布局变化
- 保留
contentPadding维持固定高度,确保所有状态下布局参数一致
修改后的代码
import 'package:beatscore/app/utils/beatscore_colors.dart'; import 'package:beatscore/main.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; // ignore: must_be_immutable class CustomTextField extends StatelessWidget { CustomTextField( {super.key, required this.onMutted, this.placeholder, this.protected = false, this.prefixIcon, this.suffixIcon, this.suffixAction, this.inputFormatters, this.validator, this.controller, this.textInputType, this.errorText}); Icon? prefixIcon; Icon? suffixIcon; bool protected; Function()? suffixAction; Function onMutted; String? placeholder; TextEditingController? controller; String? Function(String)? validator; List<TextInputFormatter>? inputFormatters; TextInputType? textInputType; String? errorText; @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.symmetric( horizontal: 16, vertical: 8, ), child: SizedBox( width: 310, child: TextFormField( keyboardType: textInputType, autovalidateMode: AutovalidateMode.onUserInteraction, validator: validator == null ? null : (value) => validator!(value!), inputFormatters: inputFormatters, onChanged: (value) => onMutted(value), cursorColor: const Color.fromARGB(255, 0, 0, 0), style: const TextStyle( fontSize: 16, color: Color.fromRGBO(30, 30, 30, 0.6), height: 1.6), obscureText: protected, controller: controller, decoration: InputDecoration( // 统一错误状态下的边框,包括聚焦错误状态 errorBorder: const OutlineInputBorder( borderRadius: BorderRadius.circular(8), borderSide: BorderSide(color: BeatscoreColors.ligthErrorRed), ), focusedErrorBorder: const OutlineInputBorder( borderRadius: BorderRadius.circular(8), borderSide: BorderSide(color: BeatscoreColors.ligthErrorRed), ), contentPadding: const EdgeInsets.symmetric( horizontal: 12.5, vertical: 12.5, ), // 让错误文本不占用空间,避免布局偏移 errorStyle: const TextStyle(height: 0, fontSize: 0), errorText: errorText, hintText: placeholder, prefixIcon: prefixIcon, suffixIcon: suffixIcon != null ? IconButton( icon: suffixIcon!, onPressed: suffixAction, ) : null, focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(8), borderSide: const BorderSide( width: 0, style: BorderStyle.none, )), filled: true, fillColor: Colors.white, border: OutlineInputBorder( borderRadius: BorderRadius.circular(8), borderSide: const BorderSide( width: 0, style: BorderStyle.none, ), ), ), ), ), ); } }
内容的提问来源于stack exchange,提问作者maremaFNX
相关产品推荐
相关产品推荐

