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

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),
    ),
  },
),

解决方案

问题核心是输入框的高度约束为范围值,且错误提示出现时默认内边距会变化,导致尺寸波动。按以下修改:

  1. 固定输入框高度:将constraints从范围约束改为固定高度,避免状态变化时高度自适应
  2. 启用紧凑模式:设置isDense: true,减少默认布局的内边距波动
  3. 调整内容内边距:适配固定高度,确保文本垂直居中

修改后的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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 03:15:55