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

Flutter动态创建自定义Widget时如何获取动态控件的输入文本

解决方案

原生实现方案(无需引入第三方包)

你当前的写法存在两个核心问题,导致无法正常获取输入值:

  • 直接维护List<Widget>存储表单实例,不符合Flutter状态驱动UI的设计逻辑,无法统一管控输入状态
  • 手机号、预订号、票号输入框绑定了全局唯一的TextEditingController,新增多个乘客表单时,所有同名字段会共用同一个控制器,输入内容会互相覆盖,无法拿到每个乘客的独立输入值

正确的实现逻辑是维护数据/控制器列表,通过数据动态渲染UI,步骤如下:

  1. 定义乘客信息的实体类,每个乘客对应独立的输入控制器,同时统一管理控制器的释放逻辑
class PassengerInfo {
  final int passengerId;
  final TextEditingController nameController;
  final TextEditingController mobileController;
  final TextEditingController reservationController;
  final TextEditingController ticketController;

  PassengerInfo({required this.passengerId})
      : nameController = TextEditingController(),
        mobileController = TextEditingController(),
        reservationController = TextEditingController(),
        ticketController = TextEditingController();

  void dispose() {
    nameController.dispose();
    mobileController.dispose();
    reservationController.dispose();
    ticketController.dispose();
  }
}
  1. 在页面状态类中,替换原来的Widget列表为乘客数据列表,维护当前乘客的最大序号
List<PassengerInfo> passengerList = [PassengerInfo(passengerId: 1)];
int currentMaxPassengerId = 1;
  1. 点击添加按钮时,往数据列表中新增乘客实例,通过setState触发UI刷新,不要直接操作Widget列表
void addNewPassenger() {
  setState(() {
    currentMaxPassengerId++;
    passengerList.add(PassengerInfo(passengerId: currentMaxPassengerId));
  });
}
  1. 改造原来的textinputPassnger方法,接收单个乘客实体作为参数,输入框绑定实体中对应的独立控制器
Widget buildPassengerFormItem(PassengerInfo passenger) {
  return Column(
    crossAxisAlignment: CrossAxisAlignment.center,
    children: [
      const SizedBox(height: 20),
      Container(
        width: 250,
        height: 30,
        child: Card(
          shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
          elevation: 5,
          child: Center(
            child: Text("Passenger Number ${passenger.passengerId}"),
          ),
        ),
      ),
      const SizedBox(height: 20),
      const Text("Passenger Name", style: TextStyle(fontSize: 17)),
      const SizedBox(height: 15),
      Inputfield(controller: passenger.nameController),
      const SizedBox(height: 20),
      const Text("Mobile", style: TextStyle(fontSize: 17)),
      const SizedBox(height: 15),
      Inputfield(controller: passenger.mobileController),
      const SizedBox(height: 20),
      const Text("Reservation number", style: TextStyle(fontSize: 17)),
      const SizedBox(height: 15),
      Inputfield(controller: passenger.reservationController),
      const SizedBox(height: 20),
      const Text("Ticket number", style: TextStyle(fontSize: 17)),
      const SizedBox(height: 15),
      Inputfield(controller: passenger.ticketController),     
    ],
  );
}
  1. 表单渲染时,直接将数据列表映射为Widget列表即可;需要获取所有输入内容时,遍历数据列表读取每个控制器的text属性就能拿到结构化数据
// 获取所有乘客提交的输入内容
List<Map<String, String>> getAllInputData() {
  return passengerList.map((item) {
    return {
      "passengerId": item.passengerId.toString(),
      "name": item.nameController.text.trim(),
      "mobile": item.mobileController.text.trim(),
      "reservationNo": item.reservationController.text.trim(),
      "ticketNo": item.ticketController.text.trim(),
    };
  }).toList();
}

注意:页面dispose生命周期中,需要遍历passengerList调用每个实例的dispose方法,释放控制器避免内存泄漏。

可简化动态表单开发的Package

如果不想手动维护控制器、表单校验逻辑,可以使用以下几个常用的成熟表单库,均原生支持动态增减表单项、自动管理输入状态、一键获取全量表单值:

  • flutter_form_builder:生态最完善的Flutter表单库,内置几乎所有常用输入组件、校验规则,动态表单实现成本极低,不需要手动管理TextEditingController
  • reactive_forms:基于响应式状态设计的表单库,支持字段状态实时同步、跨字段联动校验,适合复杂表单场景
  • dynamic_forms:支持通过JSON配置生成表单,适合表单结构需要后端动态下发的业务场景

小提示:你原有代码中"Passenger"存在拼写错误(写成了Passnger、Passanger),建议统一修正,避免后续拼写相关的bug。


内容的提问来源于stack exchange,提问作者Thank for help

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 06:30:53