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

Flutter动态添加TextFormField多输入框值同步问题

问题根因

所有动态生成的输入框共用了同一个TextEditingController实例。在Flutter中,输入框的内容完全由绑定的控制器控制,多个输入框绑定同一个控制器时,输入内容会自动同步到所有绑定的输入框。
Flutter不支持PHP里sets$numberOfTextFields这种动态变量名的写法,这类多实例场景需要用集合来管理独立的控制器实例。

修复步骤
  • 替换单个控制器为控制器列表,每个输入框对应列表里一个独立的控制器实例
  • 生成输入框时按索引绑定对应位置的控制器
  • 点击新增输入框时,同步往控制器列表添加新的控制器实例
  • 页面销毁时遍历释放所有控制器,避免内存泄漏
  • 提交表单时遍历控制器列表,获取所有输入框的内容
核心修改代码
  1. 替换状态类中的控制器定义、初始化、销毁逻辑
class _EventEditingPageState extends State<EventEditingPage> {
  final _formKey = GlobalKey<FormState>();
  // 用列表存储所有输入框的控制器,初始默认1个
  List<TextEditingController> setsControllers = [TextEditingController()];
  int numberOfTextFields = 1;

  @override
  void initState() {
    super.initState();
    // 编辑现有事件时给第一个输入框赋值
    if(widget.event != null){
      setsControllers[0].text = widget.event!.Sets;
    }
  }

  @override
  void dispose() {
    // 遍历释放所有控制器
    for (var controller in setsControllers) {
      controller.dispose();
    }
    super.dispose();
  }

  // ... 其余原有代码
}
  1. 修改输入框构建方法,按索引绑定对应控制器
// 传入索引参数区分不同输入框
Widget buildExerciseComplete(int index) => Container(
  padding: EdgeInsets.all(5.0),
  decoration: BoxDecoration(
    color: Color.fromARGB(255, 255, 200, 200),
    borderRadius: BorderRadius.circular(5.0),
    border: Border.all(width: 2.0),
  ),
  height: 50,
  child: Row(
    children: <Widget>[
      Expanded(
        child: Row(
          children: <Widget>[
            Expanded(child: buildSets(index)),
          ],
        ),
      ),
    ],
  ),
);

Widget buildSets(int index) => TextFormField(
  keyboardType: TextInputType.number,
  inputFormatters: <TextInputFormatter>[
    FilteringTextInputFormatter.digitsOnly
  ],
  style: TextStyle(fontSize: 15),
  decoration: InputDecoration(
    border: OutlineInputBorder(),
    labelText: 'Sets ${index + 1}',
  ),
  onFieldSubmitted: (_) => saveForm,
  validator: (sets) =>
      sets != null && sets.isEmpty ? 'Sets cannot be empty' : null,
  // 绑定当前索引对应的独立控制器
  controller: setsControllers[index],
);
  1. 修改动态生成逻辑和新增按钮逻辑
@override
Widget build(BuildContext context) => Scaffold(
  appBar: AppBar(
    leading: CloseButton(),
    actions: buildEditingActions(),
    backgroundColor: Colors.red,
  ),
  body: SingleChildScrollView(
    padding: EdgeInsets.all(12),
    child: Form(
      key: _formKey,
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          // 循环时传入索引
          for(int i = 0 ; i < numberOfTextFields ; i++) 
            buildExerciseComplete(i),
          buildAddMore(),
        ],
      ),
    ),
  ),
);

Widget buildAddMore() => ElevatedButton(
  onPressed: () {
    setState((){
      numberOfTextFields++;
      // 新增输入框时同步添加新的独立控制器
      setsControllers.add(TextEditingController());
    });
  },
  child: Text('Add new exercise'),  
);
  1. 修改表单提交逻辑,获取所有输入框的值
Future saveForm() async {
  final isValid = _formKey.currentState!.validate();
  if (isValid) {
    // 遍历控制器拿到所有输入框的内容
    List<String> allSetValues = setsControllers.map((e) => e.text).toList();
    
    // 后续按业务需求处理allSetValues即可
    // 示例:如果原有Event需要接收所有值,可自行调整Event类的字段类型
    // final event = Event(Sets: allSetValues);
  }
}

提示:如果后续需要给每个输入框加删除功能,删除对应行时要同步移除列表里对应索引的控制器并调用dispose,避免内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 13:57:31