# Flutter TextField 垂直居中纠错指南

> 本文档基于一次真实案例总结：修复一个简单的输入框垂直居中问题，经历了 **15+ 轮对话**，涉及多种方案反复尝试

## 📋 问题总结

### 问题描述
输入框需要实现 placeholder、光标、输入内容三者在容器中垂直居中对齐。

### 问题根因
Flutter TextField 的垂直对齐涉及**多个相互作用的属性**，修改一个属性可能影响其他元素的位置，导致"改了 A 问题引发 B 问题"的循环。

### 反复失败的原因

| 尝试次数 | 方案 | 结果 |
|----------|------|------|
| 1 | contentPadding: vertical: 10 | 整体偏下 |
| 2 | textAlignVertical: center | 只影响输入内容，placeholder 不动 |
| 3 | 移除 contentPadding | 整体偏上 |
| 4 | strutStyle + height: 1.0 | 文字被压缩，更难看 |
| 5 | Container.alignment + contentPadding: 8 | 输入内容正常，placeholder 偏下 |
| 6 | hintStyle height: 1.2 | placeholder 移动，但不够 |
| 7 | hintStyle height: 1.0 | placeholder 过于靠上 |
| 8-15 | 各种组合... | 来回折腾 |

### 根本问题
**没有一开始就理解 TextField 的渲染模型**，而是"试错式"调整参数。

---

## ✅ 正确方案（一步到位）

### 设计规格（从 Sketch 获取）
- 容器高度：36px
- 文本 Y 坐标：8px（距顶部）
- 文本高度：20px
- 字号：14px
- 行高倍数：1.43（20 ÷ 14 = 1.43）

### Flutter 正确配置

```dart
Widget _buildCenteredTextField({
  required String placeholder,
  required TextEditingController controller,
}) {
  return Container(
    height: 36,
    decoration: BoxDecoration(
      // ... 背景、圆角、阴影
    ),
    alignment: Alignment.center, // 关键：让 TextField 在容器中居中
    child: TextField(
      controller: controller,
      textAlign: TextAlign.center, // 水平居中
      // 不要使用 textAlignVertical，会导致 placeholder 和输入内容位置不一致
      style: const TextStyle(
        fontSize: 14,
        height: 1.43, // 关键：与 hintStyle 保持一致
        fontWeight: FontWeight.w600,
      ),
      decoration: InputDecoration(
        hintText: placeholder,
        hintStyle: const TextStyle(
          fontSize: 14,
          height: 1.43, // 关键：与 style 完全一致
          fontWeight: FontWeight.w600,
        ),
        contentPadding: EdgeInsets.zero, // 关键：清除默认 padding
        isDense: true, // 关键：移除额外空间
        border: InputBorder.none,
        enabledBorder: InputBorder.none,
        focusedBorder: InputBorder.none,
      ),
    ),
  );
}
```

### 关键原则

| 属性 | 作用 | 注意事项 |
|------|------|----------|
| `Container.alignment: Alignment.center` | 让 TextField 整体在容器中居中 | 必须配合 `contentPadding: EdgeInsets.zero` |
| `style.height` 和 `hintStyle.height` | 控制行高 | **必须相同**，否则 placeholder 和输入内容位置不一致 |
| `contentPadding: EdgeInsets.zero` | 清除默认间距 | 让 Container.alignment 生效 |
| `isDense: true` | 移除 TextField 默认空间 | 减少干扰因素 |
| `textAlignVertical` | **不推荐使用** | 只影响输入内容，不影响 placeholder |

---

## 📌 简版纠错指南

### TextField 垂直居中三步法

```dart
// Step 1: Container 提供高度和居中
Container(
  height: 36,
  alignment: Alignment.center,
  child: TextField(
    // Step 2: style 和 hintStyle 使用相同的 height
    style: TextStyle(fontSize: 14, height: 1.43),
    decoration: InputDecoration(
      hintStyle: TextStyle(fontSize: 14, height: 1.43),
      // Step 3: 清除 padding，启用 isDense
      contentPadding: EdgeInsets.zero,
      isDense: true,
    ),
  ),
)
```

### 禁止事项

1. ❌ **禁止 style.height 和 hintStyle.height 不一致** - 会导致 placeholder 和输入内容位置不同
2. ❌ **禁止同时使用 textAlignVertical 和 height** - 会产生冲突
3. ❌ **禁止 strutStyle + forceStrutHeight** - 可能压缩文字
4. ❌ **禁止反复调整 contentPadding 试错** - 先确定行高配置

### 调试顺序

遇到 TextField 垂直对齐问题时，按以下顺序检查：

1. **先确认设计规格** - 容器高度、文本高度、计算行高倍数
2. **配置 height** - style 和 hintStyle 使用相同的 height
3. **配置 Container** - alignment: Alignment.center
4. **清除干扰** - contentPadding: EdgeInsets.zero, isDense: true
5. **移除冲突属性** - 不要用 textAlignVertical 和 strutStyle

---

## 🎯 案例复盘

### 为什么需要 15+ 轮对话？

| 问题 | 正确做法 |
|------|----------|
| 没有先计算行高倍数 | 从设计稿提取：文本高度 ÷ 字号 = height |
| 逐个尝试属性 | 一次性配置完整方案 |
| 改了 A 引发 B | 理解属性之间的关系 |
| 没有统一 style 和 hintStyle | 两者必须完全一致 |

### 正确的工作流

```
1. 从 Sketch 获取完整规格（容器高度、文本 Y 坐标、文本高度）
2. 计算 height = 文本高度 ÷ 字号
3. 一次性配置完整方案（Container.alignment + 相同 height + contentPadding.zero + isDense）
4. 验证三者（placeholder、光标、输入内容）是否对齐
```

---

**创建日期**: 2026-01-19  
**案例来源**: 汇款记录筛选弹窗金额输入框  
**解决方案**: Container.alignment + 统一 height + contentPadding.zero
