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

Flutter中如何触发操作时移除StatefulWidget内指定Row实现动态表单

Flutter动态表单增删行实现方案

核心问题说明

你原有代码存在两个核心问题导致删除功能无法正常生效:

  • 每次build方法执行时都会重新创建两个Row并加入Rows数组,即使之前删除了某行,页面下次重绘又会恢复成两行
  • 直接将Widget作为状态存储不符合Flutter设计规范,应该优先存储表单数据源,再通过数据源动态构建Widget

实现逻辑

我们通过维护表单数据源的方式实现动态增删:

  1. 定义表单项的数据结构,存储每个输入行的标签、文本编辑控制器(用于获取用户输入内容)
  2. State中仅维护表单项数据数组,不直接存储Row组件
  3. build方法遍历数据源数组,动态生成对应的Row组件
  4. 删除按钮点击时,通过索引删除数据源中对应项,调用setState触发重绘即可完成行删除
  5. 若需新增行,只需往数据源数组中添加新的表单项,调用setState即可

完整可运行代码

import 'package:flutter/material.dart';

// 定义表单项数据模型
class FormItem {
  final String label;
  final TextEditingController controller;
  final EdgeInsets? margin;

  FormItem({
    required this.label,
    required this.controller,
    this.margin,
  });
}

class EditForm2 extends StatefulWidget {
  @override
  _EditForm2State createState() => _EditForm2State();
}

class _EditForm2State extends State<EditForm2> {
  // 维护表单项数据源,而不是Row数组
  late List<FormItem> _formItems;

  @override
  void initState() {
    super.initState();
    // 初始化两个默认表单项
    _formItems = [
      FormItem(
        label: 'Link',
        controller: TextEditingController(text: 'test link'),
        margin: const EdgeInsets.symmetric(horizontal: 30),
      ),
      FormItem(
        label: 'Geo',
        controller: TextEditingController(text: '0.50;0.44'),
        margin: const EdgeInsets.only(left: 30, right: 30, bottom: 50),
      ),
    ];
  }

  @override
  void dispose() {
    // 销毁所有控制器,防止内存泄漏
    for (var item in _formItems) {
      item.controller.dispose();
    }
    super.dispose();
  }

  // 删除行方法
  void _deleteRow(int index) {
    setState(() {
      // 先销毁对应控制器
      _formItems[index].controller.dispose();
      // 从数据源中移除对应项
      _formItems.removeAt(index);
    });
  }

  @override
  Widget build(BuildContext context) {
    // 动态构建所有Row
    List<Row> rows = _formItems.asMap().entries.map((entry) {
      int index = entry.key;
      FormItem item = entry.value;
      return Row(
        children: [
          Expanded(
            flex: 3,
            child: Container(
              margin: item.margin,
              child: Text(
                item.label,
                style: const TextStyle(
                  color: Colors.black54,
                  fontSize: 20.0,
                  letterSpacing: 0,
                  fontWeight: FontWeight.normal,
                ),
              ),
            ),
          ),
          Expanded(
            flex: 6,
            child: Container(
              margin: item.margin,
              child: TextFormField(
                controller: item.controller,
              ),
            ),
          ),
          Container(
            margin: const EdgeInsets.only(right: 30.0),
            child: Ink(
              decoration: const ShapeDecoration(
                color: Colors.red,
                shape: CircleBorder(),
              ),
              child: IconButton(
                icon: const Icon(
                  Icons.remove,
                  color: Colors.white,
                ),
                // 点击调用删除方法,传入当前行索引
                onPressed: () => _deleteRow(index),
              ),
            ),
          ),
        ],
      );
    }).toList();

    return Column(children: rows);
  }
}

新增行扩展

如果需要实现新增行功能,只需添加如下方法,在页面新增按钮中调用即可:

void _addNewRow() {
  setState(() {
    _formItems.add(FormItem(
      label: '新项${_formItems.length + 1}',
      controller: TextEditingController(text: ''),
      margin: const EdgeInsets.symmetric(horizontal: 30),
    ));
  });
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 10:54:02