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

Flutter如何在按钮点击时获取列表渲染的TextEditingController值

问题分析与解决方案

你的问题根源在于每次ListView.builder重建列表项时都会重新调用editableAdress(),这会重复创建TextEditingController实例,并且你添加到addressesList里的只是控制器的初始文本值,后续输入更新根本不会同步到列表里的对象。

要实现点击按钮时一次性获取所有输入值,不需要提前维护对象列表,只需要统一管理所有列表项的控制器即可,具体做法如下:


1. 统一管理控制器列表

在你的State类里定义一个存储控制器的列表,每个元素包含当前列表项的两个输入控制器:

// 用元组存储每组输入的两个控制器,也可以自定义类替代
List<({TextEditingController nameCtrl, TextEditingController secondNameCtrl})> _controllers = [];

2. 初始化控制器

在initState里根据列表长度(这里是6)初始化所有控制器,同时设置初始文本:

@override
void initState() {
  super.initState();
  // 假设你有一个初始地址列表addresses,长度为6
  for (var i = 0; i < 6; i++) {
    final address = addresses[i]; // 替换成你的初始地址数据源
    _controllers.add(
      (
        nameCtrl: TextEditingController(text: address.adrName1),
        secondNameCtrl: TextEditingController(text: address.adrName2),
      ),
    );
  }
}

3. 修改列表项构建逻辑

把editableAdress()改成带控制器参数的方法,直接使用控制器列表中对应位置的实例:

ListView.builder(
  controller: _deviceScroll,
  itemCount: 6,
  itemBuilder: (BuildContext context, int index) {
    final ctrlGroup = _controllers[index];
    return _editableAddress(ctrlGroup);
  },
);

// 接收外部传入的控制器,不再内部重复创建
Widget _editableAddress(({TextEditingController nameCtrl, TextEditingController secondNameCtrl}) ctrlGroup) {
  return Column(
    children: [
      Text('NAME', style: headingStyle),
      const SizedBox(height: 10),
      Column(
        children: [
          editableTextField(context, ctrlGroup.nameCtrl, 'Person 1 / Firma'),
          const SizedBox(height: 10),
          editableTextField(context, ctrlGroup.secondNameCtrl, 'Person 2'),
        ],
      ),
    ],
  );
}

4. 点击按钮获取所有值

在按钮的点击事件里,遍历控制器列表,直接读取每个控制器的text生成Address对象:

ElevatedButton(
  onPressed: () {
    // 一次性提取所有输入的最新值
    final List<Address> allAddresses = _controllers.map((ctrls) {
      return Address(
        adrName1: ctrls.nameCtrl.text,
        adrName2: ctrls.secondNameCtrl.text,
      );
    }).toList();
    
    // 这里对allAddresses做后续业务处理
    print(allAddresses);
  },
  child: const Text('获取所有地址'),
)

5. 释放控制器资源

记得在dispose里销毁所有控制器,避免内存泄漏:

@override
void dispose() {
  for (var ctrls in _controllers) {
    ctrls.nameCtrl.dispose();
    ctrls.secondNameCtrl.dispose();
  }
  super.dispose();
}

方案优势

  • 控制器仅在initState创建一次,不会因列表项重建重复生成
  • 所有控制器统一保存在State中,点击按钮时可直接获取最新输入文本
  • 无需提前维护addressesList,完全在需要时才生成目标对象列表

内容的提问来源于stack exchange,提问作者Salman Akbar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 20:12:42