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

Flutter 列表滑动删除后如何撤销恢复已删除的指定索引元素

Flutter列表滑动删除后撤销恢复功能实现方案

实现思路

不需要引入第三方插件,自行维护一个后进先出的删除历史栈即可实现需求:每次删除元素时,将被删除的元素和它当时被删除的索引一起存入栈中,撤销时从栈顶取出最近一次的删除记录,将元素插回原删除位置即可。

核心代码实现

import 'package:flutter/material.dart';

class ContactListPage extends StatefulWidget {
  const ContactListPage({super.key});

  @override
  State<ContactListPage> createState() => _ContactListPageState();
}

class _ContactListPageState extends State<ContactListPage> {
  // 联系人列表,若需保留前导零建议使用String类型存储
  List<String> cont = ["090", "000", "98", "090", "767"];
  // 删除历史栈,存储被删除元素和对应的删除位置
  List<Map<String, dynamic>> _deleteStack = [];

  // 执行删除操作
  void deleteItem(int index) {
    // 先记录删除信息到栈中
    _deleteStack.add({
      "index": index,
      "item": cont[index],
    });
    // 执行列表删除
    cont.removeAt(index);
    setState(() {});
    // 可选:弹出带撤销按钮的提示
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(
        content: const Text("已删除1条联系人"),
        action: SnackBarAction(label: "撤销", onPressed: undoDelete),
        duration: const Duration(seconds: 3),
      ),
    );
  }

  // 执行撤销操作
  void undoDelete() {
    if (_deleteStack.isEmpty) return;
    // 取出最近一次删除记录
    final lastDelete = _deleteStack.removeLast();
    // 将元素插回原删除位置
    cont.insert(lastDelete["index"], lastDelete["item"]);
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ListView.builder(
        itemCount: cont.length,
        itemBuilder: (context, index) {
          // 可直接包裹Dismissible实现滑动删除效果
          return Dismissible(
            key: Key(cont[index]),
            direction: DismissDirection.endToStart,
            onDismissed: (direction) => deleteItem(index),
            background: Container(
              color: Colors.red,
              alignment: Alignment.centerRight,
              padding: const EdgeInsets.only(right: 20),
              child: const Icon(Icons.delete, color: Colors.white),
            ),
            child: ListTile(title: Text(cont[index])),
          );
        },
      ),
    );
  }
}

场景验证

对应你给出的示例,运行逻辑完全匹配:

  1. 初始列表:["090", "000", "98", "090", "767"]
  2. 第一次删除索引0的元素:栈存入{"index":0, "item":"090"},列表变为["000", "98", "090", "767"]
  3. 第二次删除索引0的元素:栈存入{"index":0, "item":"000"},列表变为["98", "090", "767"]
  4. 首次点击撤销:取出栈顶最近的删除记录,将"000"插入回索引0位置,列表变为["000", "98", "090", "767"]

扩展说明

  • 天然支持多步撤销,每次调用undoDelete就恢复上一步操作,直到栈为空
  • 若需要限制最大撤销步数,每次存入栈时判断长度,超过上限就移除最早的栈底记录即可
  • 批量删除场景可将批量删除的所有元素、对应索引存入栈的单个节点,恢复时批量插入即可
  • 逻辑可无缝适配Provider、Bloc等各类状态管理方案,只需将列表和删除栈移到对应状态类中即可

内容的提问来源于stack exchange,提问作者Gbenga B Ayannuga

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 03:24:08