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

Flutter ListView多选删除后高亮状态未清除问题求助

Flutter ListView多选删除后高亮状态残留问题解决

问题描述

实现ListView多选删除功能时,选中多项执行删除操作后,数据已成功从Hive中移除,但原位置的Widget仍保持选中高亮状态。

问题原因

  1. 子组件独立维护选中状态:每个CustomCard自行管理selected布尔值,ListView.builder复用Widget时,旧的选中状态不会自动重置。
  2. Hive数据加载逻辑有缺陷:loadTransactions方法每次调用都会向静态列表追加数据,导致删除后列表数据重复。

解决方案

1. 统一由父组件管理选中状态

将选中状态的控制权移至MultiSelect组件,CustomCard不再自行维护状态,而是根据父组件的选中列表动态判断是否高亮。

修改MultiSelect代码

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

  @override
  State<MultiSelect> createState() => _MultiSelectState();
}

class _MultiSelectState extends State<MultiSelect> {
  late List<Transaction> selectedTransactions;

  @override
  void initState() {
    super.initState();
    HiveAPI.loadTransactions();
    selectedTransactions = [];
  }

  void toggleSelection(Transaction item) {
    setState(() {
      selectedTransactions.contains(item) 
          ? selectedTransactions.remove(item) 
          : selectedTransactions.add(item);
    });
  }

  void delete() {
    setState(() {
      HiveAPI.deleteTransaction(selectedTransactions);
      selectedTransactions = [];
      HiveAPI.loadTransactions();
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Multi Select Example"),
        actions: <Widget>[
          IconButton(
            icon: const Icon(Icons.delete),
            onPressed: delete,
          ),
        ],
      ),
      body: ListView.builder(
          itemCount: HiveAPI.transactions.length,
          itemBuilder: (context, index) {
            final transaction = HiveAPI.transactions[index];
            return CustomCard(
              isSelected: selectedTransactions.contains(transaction),
              onPress: () => toggleSelection(transaction),
              transaction: transaction,
            );
          }),
    );
  }
}

修改CustomCard为无状态组件

class CustomCard extends StatelessWidget {
  const CustomCard({
    Key? key,
    required this.transaction,
    required this.onPress,
    required this.isSelected,
  }) : super(key: key);

  final Transaction transaction;
  final VoidCallback onPress;
  final bool isSelected;

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: onPress,
      child: Container(
        padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 8.0),
        decoration: BoxDecoration(
          color: isSelected ? Colors.lime.shade100 : Colors.transparent,
          borderRadius: const BorderRadius.all(Radius.circular(16)),
        ),
        child: Row(
          children: [
            Container(
              padding: const EdgeInsets.all(8.0),
              decoration: BoxDecoration(
                color: isSelected ? Colors.lime : Colors.black,
                borderRadius: const BorderRadius.all(Radius.circular(200)),
              ),
              child: Icon(
                isSelected ? Icons.check : Icons.wallet,
                color: isSelected ? Colors.black : Colors.white,
              ),
            ),
            const SizedBox(width: 8),
            Text(
              transaction.title,
              style: Theme.of(context).textTheme.bodyText2,
            ),
          ],
        ),
      ),
    );
  }
}

2. 修复HiveAPI数据加载逻辑

在loadTransactions方法中先清空现有列表,避免重复添加数据:

class HiveAPI {
  static const String boxKey = 'transactionBox';
  static const String transactionsDataKey = 'transactions';

  static final box = Hive.box(boxKey);
  static final List<Transaction> transactions = [];

  static void loadTransactions() {
    transactions.clear(); // 清空旧数据,避免重复加载
    final data = box.get(transactionsDataKey);
    if (data != null) {
      for (var transaction in data) {
        transactions.add(
          Transaction(
            transaction[0],
            transaction[1],
            transaction[2],
            transaction[3],
            transaction[4],
          ),
        );
      }
    }
  }

  static void _updateTransactions() {
    final List transactionsPrimitive = [];

    for (var transaction in transactions) {
      transactionsPrimitive.add([
        transaction.title,
        transaction.category,
        transaction.amount,
        transaction.type,
        transaction.date,
      ]);
    }

    box.put(transactionsDataKey, transactionsPrimitive);
  }

  static void deleteTransaction(List<Transaction> selectedTransaction) {
    transactions.removeWhere((item) => selectedTransaction.contains(item));
    _updateTransactions();
  }
}

效果说明

修改后,删除操作执行时:

  • 父组件清空选中列表并触发重建,ListView会根据最新数据渲染
  • 每个CustomCard动态读取父组件的选中状态,彻底解决高亮残留问题
  • Hive加载数据时不再重复添加,保证列表数据准确

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 20:25:22