Flutter:如何防止TextFormField显示验证消息时尺寸收缩?
解决TextFormField不同状态下尺寸不一致问题
输入框在未聚焦、显示验证消息时尺寸存在明显差异(对比图如下),需要让它在聚焦、失焦、显示错误提示时保持固定尺寸。
未聚焦状态:
显示验证消息状态:
现有代码
TextFormField( autovalidateMode: AutovalidateMode.onUserInteraction, validator: (value) { if (value == null || value.isEmpty) { return "Enter email or phone to continue"; } else if (widget.model.isPhone && value.length != 10) { return "Enter a valid 10-digit phone number"; } else if (!widget.model.isPhone && !RegExp(r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$") .hasMatch(value)) { return "Enter a valid email address"; } return null; }, controller: widget.model.emailOrPhoneTEC, focusNode: phoneFocusNode, onChanged: (value) { setState(() { widget.model.isPhone = RegExp(r'^[0-9]+$').hasMatch(value); if (!widget.model.isPhone) { widget.model.user.email = value.toString(); widget.model.user.mobile = ""; } else { widget.model.user.mobile = value.toString(); widget.model.user.email = ""; } }); }, keyboardType: TextInputType.text, decoration: InputDecoration( hintText: "Phone / Email", hintStyle: TextStyle( color: Colors.grey[700], fontFamily: montserratMedium), constraints: BoxConstraints( minHeight: 40.h, maxHeight: 60.h, ), contentPadding: EdgeInsets.symmetric(horizontal: 12, vertical: 0), prefix: widget.model.isPhone ? Padding( padding: const EdgeInsets.only(left: 12), child: Text( '+91', style: TextStyle( fontFamily: montserratMedium), ), ) : null, prefixIconConstraints: BoxConstraints(minWidth: 40, minHeight: 0), border: OutlineInputBorder( borderRadius: BorderRadius.circular(6), borderSide: BorderSide(color: Colors.grey), ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(6), borderSide: BorderSide(color: Colors.grey), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(6), borderSide: BorderSide(color: Colors.grey), ), errorBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(6), borderSide: BorderSide(color: Colors.red), ), focusedErrorBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(6), borderSide: BorderSide(color: Colors.red), ), }, ),
解决方案
问题核心是输入框的高度约束为范围值,且错误提示出现时默认内边距会变化,导致尺寸波动。按以下修改:
- 固定输入框高度:将
constraints从范围约束改为固定高度,避免状态变化时高度自适应 - 启用紧凑模式:设置
isDense: true,减少默认布局的内边距波动 - 调整内容内边距:适配固定高度,确保文本垂直居中
修改后的InputDecoration代码:
decoration: InputDecoration( isDense: true, // 关键:消除状态切换时的内边距变化 hintText: "Phone / Email", hintStyle: TextStyle( color: Colors.grey[700], fontFamily: montserratMedium), constraints: BoxConstraints.tightFor(height: 50.h), // 固定高度,替换原范围约束 contentPadding: EdgeInsets.symmetric(horizontal: 12, vertical: 16), // 适配固定高度的垂直内边距 prefix: widget.model.isPhone ? Padding( padding: const EdgeInsets.only(left: 12), child: Text( '+91', style: TextStyle( fontFamily: montserratMedium), ), ) : null, prefixIconConstraints: BoxConstraints(minWidth: 40, minHeight: 0), border: OutlineInputBorder( borderRadius: BorderRadius.circular(6), borderSide: BorderSide(color: Colors.grey), ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(6), borderSide: BorderSide(color: Colors.grey), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(6), borderSide: BorderSide(color: Colors.grey), ), errorBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(6), borderSide: BorderSide(color: Colors.red), ), focusedErrorBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(6), borderSide: BorderSide(color: Colors.red), ), ),
如果仍有宽度波动,检查prefix的Padding是否动态变化,确保prefixIconConstraints的minWidth足够容纳+91文本,避免输入框宽度被撑开。
内容的提问来源于stack exchange,提问作者Arnab Ghosh
相关产品推荐
相关产品推荐

