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

Flutter集成flutter_tindercard后删除元素ListView不更新如何解决

问题原因

  • 最核心的错误是element.indexOf(element)的用法错误:你对单个字符串元素调用自身的indexOf方法,返回值永远是0,所以每次只会删除卡片列表的第一个元素,根本删不掉你当前操作的卡片,自然就会出现卡片不消失、底部元素不上移的问题。
  • 所有卡片共用同一个CardController实例,会触发控件的操作冲突。
  • 提前把Widget实例存在列表里的写法不合理,Flutter应该靠状态数据驱动UI生成,而不是预存Widget。

修复方案

调整代码逻辑,用索引遍历数据源生成卡片,操作时直接对应当前卡片的索引,同时给每个卡片单独分配控制器,完整可运行代码如下:

import 'package:flutter/material.dart';
import 'package:flutter_tindercard/flutter_tindercard.dart';

class ExampleHomePage extends StatefulWidget {
  @override
  _ExampleHomePageState createState() => _ExampleHomePageState();
}

class _ExampleHomePageState extends State<ExampleHomePage>
    with TickerProviderStateMixin {
  List approved = [];
  List refused = [];

  List<String> welcomeImages = [
    "https://images.unsplash.com/photo-1631636176993-759dea1a1300?ixid=MnwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHw0fHx8ZW58MHx8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=500&q=60",
    "https://images.unsplash.com/photo-1631634176568-f543af6a41de?ixid=MnwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHw3fHx8ZW58MHx8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=500&q=60",
    "https://images.unsplash.com/photo-1631691971564-adf9419d904e?ixid=MnwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHwxM3x8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=500&q=60",
    "https://images.unsplash.com/photo-1631641906574-24adb8594649?ixid=MnwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHwxMnx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=500&q=60",
    "https://images.unsplash.com/photo-1593642702821-c8da6771f0c6?ixid=MnwxMjA3fDF8MHxlZGl0b3JpYWwtZmVlZHwxMXx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=500&q=60",
    "https://images.unsplash.com/photo-1631621461675-e61a1f28d3d6?ixid=MnwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHw0NHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=500&q=60"
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        width: double.infinity,
        child: ListView(
          // 直接通过数据源动态生成卡片,不预存Widget
          children: welcomeImages.asMap().entries.map((entry) {
            int index = entry.key;
            String image = entry.value;
            // 每个卡片单独分配控制器
            CardController controller = CardController();
            return TinderCarder(
              image: image,
              controller: controller,
              onLeftPress: () {
                setState(() {
                  // 左滑加入拒绝列表
                  refused.add(welcomeImages.removeAt(index));
                  print('拒绝了第$index项,剩余卡片数:${welcomeImages.length}');
                });
              },
              onRightPress: () {
                setState(() {
                  // 右滑加入通过列表
                  approved.add(welcomeImages.removeAt(index));
                  print('通过了第$index项,剩余卡片数:${welcomeImages.length}');
                });
              },
            );
          }).toList(),
        ),
      ),
    );
  }
}

class TinderCarder extends StatelessWidget {
  final String image;
  Function onLeftPress;
  Function onRightPress;
  CardController controller;

  TinderCarder(
      {required this.image,
      required this.controller,
      required this.onLeftPress,
      required this.onRightPress});

  @override
  Widget build(BuildContext context) {
    return Container(
      height: 200,
      child: TinderSwapCard(
        orientation: AmassOrientation.BOTTOM,
        totalNum: 1,
        stackNum: 3,
        swipeEdge: 4.0,
        maxWidth: double.infinity,
        maxHeight: MediaQuery.of(context).size.width * 0.9,
        minWidth: MediaQuery.of(context).size.width * 0.8,
        minHeight: MediaQuery.of(context).size.width * 0.8,
        cardBuilder: (context, index) => Card(
          child: Image.network(
            image,
            width: double.infinity,
            fit: BoxFit.cover,
          ),
        ),
        cardController: controller,
        swipeUpdateCallback: (DragUpdateDetails details, Alignment align) {},
        swipeCompleteCallback: (CardSwipeOrientation orientation, int index) {
          if (orientation == CardSwipeOrientation.LEFT) {
            onLeftPress();
          } else if (orientation == CardSwipeOrientation.RIGHT) {
            onRightPress();
          }
        },
      ),
    );
  }
}

调整说明

  • 移除了预存的卡片Widget列表,改为在build方法中通过welcomeImages数据源动态生成卡片,符合Flutter状态驱动UI的设计逻辑。
  • 通过asMap().entries遍历拿到每个元素的真实索引,操作时直接删除对应下标的数据源元素,调用setState后UI会自动刷新,卡片就会正常移除,底部元素自动上移。
  • 每个卡片单独创建CardController实例,避免操作冲突。
  • 补充了通过/拒绝列表的添加逻辑,符合需求。

内容的提问来源于stack exchange,提问作者x-DZ-Ax

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 18:09:04