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

Flutter中删除列表指定自定义TextFormField避免误删最后项的方案

问题解决:Flutter列表删除组件异常 & 可自我删除组件实现

问题原因

你遇到的删除异常是因为Flutter的Widget复用机制:当列表元素变化时,Flutter默认根据Widget的类型和位置复用现有组件,而非重新创建。由于你的TestWidget没有设置唯一Key,删除元素后UI无法正确映射更新后的列表,导致视觉上总是删除最后一个组件。

修复删除功能的代码

给每个TestWidget添加唯一Key,并简化组件代码:

import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(primarySwatch: Colors.blue),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  final String title;

  const MyHomePage({
    super.key,
    required this.title,
  });

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  List<int> _listID = [0, 1, 2, 3];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text(widget.title)),
      body: Column(
        children: _listID.map((id) {
          return TestWidget(
            key: ValueKey(id), // 添加唯一Key,解决复用问题
            id: id,
            onPressed: () {
              setState(() {
                _listID.remove(id);
              });
            },
          );
        }).toList(),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {},
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}

class TestWidget extends StatefulWidget {
  final VoidCallback? onPressed;
  final int id;

  const TestWidget({
    super.key,
    this.onPressed,
    required this.id,
  });

  @override
  State<TestWidget> createState() => _TestWidgetState();
}

class _TestWidgetState extends State<TestWidget> {
  @override
  Widget build(BuildContext context) {
    return TextFormField(
      decoration: InputDecoration(
        labelText: widget.id.toString(),
        suffixIcon: IconButton(
          icon: const Icon(Icons.clear),
          onPressed: widget.onPressed,
        ),
      ),
    );
  }
}

实现可自我删除的组件

让组件自身触发删除逻辑,通过回调通知父组件更新列表:

// 替换原有TestWidget的可自我删除版本
class SelfRemovableWidget extends StatefulWidget {
  final int id;
  final Function(int) onDelete; // 传递要删除的ID给父组件

  const SelfRemovableWidget({
    super.key,
    required this.id,
    required this.onDelete,
  });

  @override
  State<SelfRemovableWidget> createState() => _SelfRemovableWidgetState();
}

class _SelfRemovableWidgetState extends State<SelfRemovableWidget> {
  @override
  Widget build(BuildContext context) {
    return TextFormField(
      decoration: InputDecoration(
        labelText: widget.id.toString(),
        suffixIcon: IconButton(
          icon: const Icon(Icons.clear),
          onPressed: () {
            widget.onDelete(widget.id); // 组件自身触发删除
          },
        ),
      ),
    );
  }
}

// 在MyHomePage中使用该组件
body: Column(
  children: _listID.map((id) {
    return SelfRemovableWidget(
      key: ValueKey(id),
      id: id,
      onDelete: (deleteId) {
        setState(() {
          _listID.remove(deleteId);
        });
      },
    );
  }).toList(),
),

额外注意

如果列表中可能出现重复ID,建议使用唯一标识符(如UUID)替代int,避免remove(id)删除错误的元素。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 06:25:17